Forum Discussion
RobDiazMarino
May 21, 2020Copper Contributor
authentication.authenticate() opens in external browser tab instead of pop-up window on first call
Hi there,
We're developing an app for Teams and found a problem where the first time we call microsoftTeams.authentication.authenticate() in the Desktop app (both Mac and Windows) it opens the specified url in an external browser window/tab instead of a pop-up window. When this happens, authentication gets stuck and can't complete, so the tab never closes.
It's nearly impossible for us to debug why the external browser tab can't complete the authentication - the desktop app blocks our local builds, and also seems to remove debugger statements when we run from a dev deployment. The bug is not reproducible when using the Teams web app (which does work with our local builds). But this is probably beside the point.
When the external browser tab problem happens, there is an error message in the console for the Teams tab that made the authenticate() call as follows: Error during Teams authentication: Error: Unable to send AtomFrameHostMsg_Message_Sync. Full stack info:
Uncaught (in promise) Error: Unable to send AtomFrameHostMsg_Message_Sync
at EventEmitter.ipcRenderer.sendSync (<anonymous>:1717:18)
at Object.exports.invokeSync (<anonymous>:1692:41)
at Object.<anonymous> (<anonymous>:3229:22)
at Object.require.34../../common/atom-binding-setup (<anonymous>:3374:4)
at o (<anonymous>:2:273)
at r (<anonymous>:2:439)
at <anonymous>:2:468
Now, the interesting thing is that any microsoftTeams.authentication.authenticate() call after this works correctly - it opens in a pop-up window and authentication works without problems. Refresh the page and we're back to square one - first authenticate() behaves incorrectly but subsequent calls work as expected.
The problem was that .initialize() method is not a synchronous operation. Digging into the API docs shows that .initialize() takes a callback function as a parameter. So wrapping this in a promise and chaining the authentication call to happen afterward fixed the problem.
- RobDiazMarinoCopper Contributor
The problem was that .initialize() method is not a synchronous operation. Digging into the API docs shows that .initialize() takes a callback function as a parameter. So wrapping this in a promise and chaining the authentication call to happen afterward fixed the problem.
- matt131Copper Contributor
Anything else special that you did to get this to work in generarl? Everything works as expected in the web version of Teams. However in the desktop client it always opens in an external browser. I tried waiting for intialization like below:
microsoftTeams.initialize(() => { microsoftTeams.authentication.authenticate({ url: myUrl, ......
However this completley breaks the call and it no longer even opens in an external browser. As you mentioned debugging is impossible in the desktop client. Any tips?
- RobDiazMarinoCopper Contributor
matt131 The code you posted seems like it should work, so I'm not sure exactly what's wrong. I'll share a little bit more about how we set up our code and maybe it will help.
We created our own wrapper for the MS Teams API like so (there is a lot more to it but I've extracted only the parts pertinent to this problem):import * as microsoftTeams from '@microsoft/teams-js' let initializePromise = null export default { init() { if (!initializePromise) { initializePromise = new Promise((resolve) => { microsoftTeams.initialize(resolve) }) } return initializePromise }, authenticate() { return this.init().then(() => { return new Promise((resolve, reject) => { // Launch the MS Teams Login flow microsoftTeams.authentication.authenticate({ url: window.location.origin + 'loginpath', successCallback: resolve, failureCallback: reject, width: 500, height: 500 }) }).catch(error => { console.error('Error during Teams authentication: ', error) throw error }) }) } }
Setting up our init function in this way means we can call it at the beginning of any operation that requires the MS Teams API to ensure it has been initialized properly first. If it has already been called once then it resolves immediately from then on.
Hope this helps!