Closed shabbir-dhangot closed 3 months ago
You can find more issue detail here. https://techcommunity.microsoft.com/t5/teams-developer/teamsfx-react-3-0-2-teamsusercredential-gettoken-results-in/m-p/3984411. This has raised by different user.
@shabbir-dhangot Does your application has login related logic (by using TeamsUserCredential.login(...)
)? The UiRequiredError
means the application needs user to login explicitly in order to acquire the token. So the quick solution is trigger the login logic when your application gets the error. After that, your session storage should have the token and the TeamsFx SDK can acquire token from there.
To provide more technical background:
The TeamsUserCredential.getToken(...)
function will try to acquire cached token from session storage first. If there's no cached token, it will leverage MSAL's silent login functionality to login current user silently. This is why you didn't meet UiRequiredError
error previously. If both does not work, it will throw UiRequiredError
asking people to login in order to acquire the token, which is your current situation. The MSAL's silent login functionality is not guaranteed to always work under every situation. So please trigger the login flow as suggested above if you got UiRequiredError
error.
Hi,
Observing exactly the same issue in a web client (FireFox, Edge - Classic and New Teams), the following code is used:
export default function TeamsApp() {
console.log('Running in `Teams` mode', process.env.REACT_APP_START_LOGIN_PAGE_URL, process.env.REACT_APP_CLIENT_ID);
const [ channel, setChannel ] = useState<TeamsChannelIntegration | null>(null);
const [ auth, setAuth ] = useState<Auth | null>(null);
const [ error, setError ] = useState(null);
const [ teams, setTeams ] = useTeams();
const { loading, error: xError, teamsUserCredential} = useTeamsUserCredential({
clientId: process.env.REACT_APP_CLIENT_ID ?? 'unknown',
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL ?? 'unknown'
});
useEffect(() => {
(async () => {
if(teamsUserCredential) {
try {
// TODO `teamsUserCredential.login` for some reason opens popup, so use the common way for now
setChannel(TeamsChannelIntegration.build(new MSGraph(teamsUserCredential!)));
setAuth(new TeamsAuth());
console.log('... UserCredential. Before Login')
await teamsUserCredential.login(['User.Read']);
console.log('... UserCredential. After Login')
const tUser = await teamsUserCredential.getUserInfo();
console.log('... UserCredential. After User Info', tUser);
const tToken = await teamsUserCredential.getToken(['User.Read']);
console.log('... UserCredential. After Get Token', tToken);
const tGraph = new MSGraph(teamsUserCredential);
const tMe = await tGraph.getMe();
console.log('... UserCredential. Me', tMe);
setChannel(TeamsChannelIntegration.build(tGraph));
setAuth(new TeamsAuth());
} catch (e) {
console.log('Failed to Process due to', e);
}
}
})();
}, [teamsUserCredential]);
return (...);
}
And see the following output
Running in `Teams` mode https://localhost:53000/auth-start.html 0406...
Teams
Object { actionInfo: undefined, app: {…}, page: {…}, user: {…}, channel: {…}, chat: undefined, meeting: undefined, sharepoint: undefined, team: {…}, sharePointSite: {…} }
... UserCredential. After Login
... UserCredential. After User Info
Object { displayName: "Aliaksei Lebedzeu", objectId: "8f878155-9cc9-4a67-a179-4fe74dce9ac0", tenantId: "36ec...", preferredUserName: "email@x.onmicrosoft.com" }
Failed to Process due to bc.UiRequiredError: Failed to get access token cache silently, please login first: you need login first before get access token.
I see a pop-up appearing and disappearing, but it does not help
@aliaksei-lebedzeu Thanks for reporting this to us. I wasn't able to repro your issue. Can you clone https://github.com/KennethBWSong/authCodeTemplate and see whether you can repro with this template project?
@blackchoey, I attempted to use TeamsUserCredential.getToken(...), and it produced the same error as the one I shared earlier. It seems that due to tracking prevention, when Graph attempts to access the cache, it is denied, resulting in the aforementioned error. Below is code which I tried.
useEffect(() => {
if (!teamsUserCredential) {
return;
}
teamsUserCredential
.getToken("User.Read")
.then((token) => {
console.log("token acquired:", token);
})
.catch((err) => {
console.error("token acquisition failed.", err);
});
}, [teamsUserCredential, graphApiAuthenticated]);
@shabbir-dhangot you need to call the login(...)
function when you get the UiRequiredError
. You can also leverage the @microsoft/teamsfx-react
package when building react app, which handles the login for you.
In the meanwhile, can you also try this sample and see whether you will meet same issue with it? https://github.com/KennethBWSong/authCodeTemplate
Hello @blackchoey - Another developer is still facing the same issue: https://github.com/OfficeDev/microsoft-teams-library-js/issues/1994
Looks like this issue is more related to TeamsFX side but not on the Teams JS library. Could you please confirm and share your thoughts on the issue?
Hi @ChetanSharma-msft The customer is facing a difference issue (a latency issue) and it seems to be a Teams client issue as other client versions are working fine. Can you reach client team for help?
The code of getToken()
is fairly simple: https://github.com/OfficeDev/TeamsFx/blob/dev/packages/sdk/src/credential/teamsUserCredential.browser.ts#L210-L278
To brainstorm more: Since it's related to Teams client version, I'm not sure whether following function call to teams-js inside getToken()
will be impacted by different version of client:
await app.initialize()
to initialize teams-jsawait authentication.getAuthToken(params)
to get SSO tokenThe getToken()
function will print logs with timestamp. We may ask the customer to check the timestamp to identify which part consumes most of the time.
@shabbir-dhangot Does your application has login related logic (by using
TeamsUserCredential.login(...)
)? TheUiRequiredError
means the application needs user to login explicitly in order to acquire the token. So the quick solution is trigger the login logic when your application gets the error. After that, your session storage should have the token and the TeamsFx SDK can acquire token from there.To provide more technical background: The
TeamsUserCredential.getToken(...)
function will try to acquire cached token from session storage first. If there's no cached token, it will leverage MSAL's silent login functionality to login current user silently. This is why you didn't meetUiRequiredError
error previously. If both does not work, it will throwUiRequiredError
asking people to login in order to acquire the token, which is your current situation. The MSAL's silent login functionality is not guaranteed to always work under every situation. So please trigger the login flow as suggested above if you gotUiRequiredError
error.
After calling await teamsUserCredential.getToken(scopes)
I get the following error:
Failed to get access token cache silently, please login first: you need login first before get access token.
I then call await teamsUserCredential.login(scopes)
the user is able to login successfully and no error is encountered.
After login I call await teamsUserCredential.getToken(scopes)
which results in the same error as before:
Failed to get access token cache silently, please login first: you need login first before get access token.
This issue is only happening to users that are using Teams on iphone. And calls to teamsUserCredentials.getUserInfo() work.
Am I missing something?
@mr-github-user We will try to repro this. In the meanwhile, can you also try this project and see whether it has same issue as your project?
@mr-github-user We will try to repro this. In the meanwhile, can you also try this project and see whether it has same issue as your project?
Is this the project you want me to try: https://github.com/KennethBWSong/authCodeTemplate
The issue only happens for me when the app is running inside of the MacOS and ios Teams client. I'll start working with our Teams admin to see if he is okay with us adding the project to our instance.
Thanks
@mr-github-user Yes, please help try that project. In the meanwhile, you can also leverage the M365 Developer Program to test this project, as well as yours. Which should be easier than getting approval from your admin.
I am facing the same issue,
At first I call await teamsUserCredential.login(scopes)
with no error.
I then call await teamsUserCredential.getToken(scopes)
which triggers Failed to get access token cache silently, please login first: you need login first before get access token.
For me this happens on Teams web.
The issue happens when I first launch my app, if I refresh the page then it seems that getToken
succeed
Does anybody have an update on this issue ?
@mr-github-user Yes, please help try that project. In the meanwhile, you can also leverage the M365 Developer Program to test this project, as well as yours. Which should be easier than getting approval from your admin.
I cloned the repo: https://github.com/KennethBWSong/authCodeTemplate
I was able to get the app published in Teams, and can confirm that it works on the iPadOS device I am using for testing. I'm not sure this helps me out though.
My application does not use the Microsoft Graph API. I am using teamsUserCredential.getToken(scopes) to obtain an access token for my Microsoft Entra ID application. The teamsUserCredentials.getToken() works in every other client except for iOS and iPadOS.
I tried using the getToken code in my own project and still get the same error
const apiClient = createApiClient(
apiBaseUrl,
new BearerTokenAuthProvider(async () => (await teamsUserCredential.getToken(""))!.token)
);
Do you have any other suggestions on how to troubleshoot the issue? Is there anything I can provide you to help troubleshoot the issue?
Thanks
@sup3rgalou Can you try this project to see whether it has the same issue? If yes, please share the repro steps so we can repro and investigate further.
@mr-github-user Since the project we shared does not have the issue, can you compare the project with yours and find the implementation differences? The project is a previous template to demonstrate how to build a project with authentication enabled. In the meanwhile, you could also see whether it's possible to create a sample project that repros the issue. So we can repro and investigate further.
@blackchoey
@mr-github-user Since the project we shared does not have the issue, can you compare the project with yours and find the implementation differences? The project is a previous template to demonstrate how to build a project with authentication enabled. In the meanwhile, you could also see whether it's possible to create a sample project that repros the issue. So we can repro and investigate further.
I think the main difference between projects is I am not querying the graph API. I am using the library to retrieve an access token for an API that I am hosting in Azure.
I went ahead and created a test project that is using the same token logic I am using in my application. When running on teams desktop I encounter no error and I am able to retrieve the token.
On iPadOS I run the same test and I get the UiRequiredError, the same error I am encountering in my application.
Here is the sample app you can use to repro the issue: https://github.com/mr-github-user/AuthenticationSample Let me know if you run into any issues with the project. I'll help if I can.
Thanks
Thank you. We will try this sample and reach you back later.
When running the application on iOS teamsfx logs the following errors after I call teamsUserCredential.getToken:
Failed to call acquireTokenSilent. Reason: no_account_error: No account object provided to acquireTokenSilent and no active account has been set. Please call setActiveAccount or provide an account on the request..
Failed to call ssoSilent. Reason: login_required: AADSTS50058: A silent sign-in request was sent but no user is signed in. The cookies used to represent the user's session were not sent in the request to Azure AD. This can happen if the user is using Internet Explorer or Edge, and the web app sending the silent sign-in request is in different IE security zone than the Azure AD endpoint (login.microsoftonline.com). Trace ID: 8e4845da-3231-4d0c-94db-3bc2428a1b00 Correlation ID: 3a7a7a6a-618e-4dd1-a83c-d6379b4c2f77 Timestamp: 2024-01-19 22:38:28Z.
Logging in does not result in an error, and sessionStorage appears to be populated with the loginResult.sessionStorage values.
However even after logging in the teamsUserCredential.getToken() still fails.
Hope that helps.
@mr-github-user Thanks for all the information. Here's one solution: run npm install @azure/msal-browser@2.21
to your project and redeploy your app. It should work on iOS devices.
Technical background:
The auth-start.html
and auth-end.html
is using MSAL-Browser 2.21 to login users and handle login redirect response. The project does not specify the MSAL version so npm installs latest version. But in newer MSAL, the cache logic is changed so it cannot read cache from 2.21 and fallback to the ssoSilent
function. In desktop browser environment, ssoSilent
can acquire a token silently so you can get the token. But it cannot acquire the token in iOS so your app cannot work properly. Changing the MSAL version in your react app to 2.21
aligns the version between react app and auth-end.html
so it fixes the problem. There could be other solution for your issue, as long as the MSAL version is aligned. You can have your own solution based on your requirement.
Instead of downgrading msal-browser to 2.21, I decided to update the auth-start.html and auth-end.html to use a more recent version of msal-browser. It worked like a charm!!!
Both the sample I sent and my own application were built using TeamsFX inside of visual studio code. The auth-start and auth-end files are defaulted to msal-browser@2.21.0. TeamsFx in the templates package.json uses version @microsoft/teamsfx: "^2.2.0" which in turn uses "@azure/msal-browser": "^2.21.0". I think because of that new applications created with teamsfx will not work on iOS. Updating the msal-browser cdn reference in auth-start.html and auth-end.html to version 2.35.0 fixed the issue for me. I did not have to update any packages on my end by doing that.
I have been trying to get this issue fixed for a long time. Thank you for your help.!!
@mr-github-user glad to hear that! I'm going to close this issue. Feel free to open new issue when you need other support.
thank you @blackchoey & @mr-github-user! fixed it for me as well, this really should be updated in the template!
Where can we find the version mapping which can work fine between msal-browser and @microsoft/teamsfx?
@leonardjohn The issue only happens when MSAL changes its cache mechanism. Since MSAL does not provide information about its cache mechanism changes, we're not able to provide a comprehensive version mapping.
For existing project, since package-lock.json locks the version of packages, you don't need to worry about this issue. If this issue happens due to some force version upgrade, you can check package-lock.json which msal-browser version is installed and change the msal-version in auth-end.html to that version.
If you're starting a new project, it's recommended to start with the "React with Fluent UI" template which includes a backend to invoke APIs. This is the latest recommendation from Teams and avoids some login limitations brought by AAD conditional access policy, which will block user login implemented with msal-browser.
@blackchoey many thanks for your fast response. I built the teams tab application with the latest Fluent UI v9 through Teams Toolkit. we referenced msal-browse.js in auth-start.html and auth-end.html:
<script
type="text/javascript"
src="https://alcdn.msauth.net/browser/2.35.0/js/msal-browser.min.js"
integrity="sha384-o+Sncs5XJ3NEAeriM/FV8YGZrh7mZk4GfNutRTbYjsDNJxb7caCLeqiDabistgwW"
crossorigin="anonymous"></script>
I tried to add dependency @microsoft/teamsfx with version:2.3.0 and it worked well. but when I updated it to 2.3.1, then the error mentioned in this title occurred. after I checked the depencency in @microsoft/teamsfx:2.3.1 and found the msal-browser version is ^3.0.2. This is the root cause, I think.
Anyway, thanks a lot again.😊
@blackchoey many thanks for your fast response. I built the teams tab application with the latest Fluent UI v9 through Teams Toolkit. we referenced msal-browse.js in auth-start.html and auth-end.html:
<script type="text/javascript" src="https://alcdn.msauth.net/browser/2.35.0/js/msal-browser.min.js" integrity="sha384-o+Sncs5XJ3NEAeriM/FV8YGZrh7mZk4GfNutRTbYjsDNJxb7caCLeqiDabistgwW" crossorigin="anonymous"></script>
I tried to add dependency @microsoft/teamsfx with version:2.3.0 and it worked well. but when I updated it to 2.3.1, then the error mentioned in this title occurred. after I checked the depencency in @microsoft/teamsfx:2.3.1 and found the msal-browser version is ^3.0.2. This is the root cause, I think.
Anyway, thanks a lot again.😊
can you share your setup. I try your script but I doesn't work
@blackchoey many thanks for your fast response. I built the teams tab application with the latest Fluent UI v9 through Teams Toolkit. we referenced msal-browse.js in auth-start.html and auth-end.html:
<script type="text/javascript" src="https://alcdn.msauth.net/browser/2.35.0/js/msal-browser.min.js" integrity="sha384-o+Sncs5XJ3NEAeriM/FV8YGZrh7mZk4GfNutRTbYjsDNJxb7caCLeqiDabistgwW" crossorigin="anonymous"></script>
I tried to add dependency @microsoft/teamsfx with version:2.3.0 and it worked well. but when I updated it to 2.3.1, then the error mentioned in this title occurred. after I checked the depencency in @microsoft/teamsfx:2.3.1 and found the msal-browser version is ^3.0.2. This is the root cause, I think. Anyway, thanks a lot again.😊
can you share your setup. I try your script but I doesn't work
Open your VS Code
Install the latest Teams Toolkit
Create a New App:
After this, you can run this Tab Application you created on your local and try this script.
Describe the bug We have encountered a critical issue in our production application when using the latest version of Microsoft Teams. It appears that Teams has implemented Tracking Prevention for the application, causing certain functionalities to break.
In our app, during the initial load, the application relies on localStorage, which was preventing the app from loading. We managed to resolve this issue by eliminating or bypassing the use of localStorage, allowing the app to load successfully. However, after the initial load, we are facing problems with a dropdown that calls the Graph API to retrieve a list of users. This functionality works correctly with the older version of Teams, but with the newer version, we are experiencing difficulties, and the exact error message is as follows:
To Reproduce Steps to reproduce the behavior:
Expected behavior Application should work normally in new Teams application in desktop client as well.
Error GraphErrorHandler.ts:44 Uncaught (in promise) r.UiRequiredError: Failed to get access token cache silently, please login first: you need login first before get access token. at e. (teamsUserCredential.browser.ts:266:15)
at d (regeneratorRuntime.js:45:16)
at Generator. (regeneratorRuntime.js:133:17)
at Generator.throw (regeneratorRuntime.js:74:21)
at sC (asyncToGenerator.js:3:20)
VS Code Extension Information (please complete the following information):
CLI Information (please complete the following information):
Additional context App is not working only in the new teams desktop client.