SOLVED

authentication.authenticate() opens in external browser tab instead of pop-up window on first call

Copper Contributor

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.

 

 

9 Replies
best response confirmed by RobDiazMarino (Copper Contributor)
Solution

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.

@RobDiazMarino 

 

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?

@matt131 Were you able to solve this?  I'm facing the same problem. 

@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!

@RobDiazMarino@matt131 were  you able to solve the problem of pop up working only in the web App and not on the desktop App? 

I am facing the same problem and not finding a solution.

Note: I have tried the approach of ensuring microsoft.intialize is success before calling the authenticate API.

@Amey2020 Make sure you are using https protocol inside Teams Desktop

http protocol wont work in Teams Desktop

Thanks @Nithin_phil.
That was not the problem. The main issue was to ensure that the external window url starts within the application route.

@Amey2020 I know this is late, but we are experiencing the same behavior right now, however, only on citrix and / azure virtual desktop. More over, the issue seems tied to the windows config, as the issue stays within the same session, while switching accounts does not make a difference.

 

So:
Windows user A logs in, teams user A logs in -> issue
Windows user A logs in, teams user B logs in -> issue
Windows user B logs in, teams user A logs in -> no issue
Windows user B logs in, teams user B logs in -> no issue

Our code DOES use the callback of initialize method to call authenticate.

 

Can you please explain what you mean by "The main issue was to ensure that the external window url starts within the application route."

Please explain what do you mean with 'application route'. I have the same issue. The popup opens with Microsoft Teams local browser but it doesnt work after publishing the solution in AWS. It gives the error not initialised. I tried it in the Teams Desktop client as well. I developed the app using "Teams Toolkit App Blazor". I added the Teams Authentication package and implemented my own code to authenticate Identity server. So it has  AuthStart page and AuthEnd page for redirecting as well. 
1 best response

Accepted Solutions
best response confirmed by RobDiazMarino (Copper Contributor)
Solution

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.

View solution in original post