Search code examples
vue.jsweb-applicationssingle-sign-onmicrosoft-teamsazure-ad-msal

Web app that runs in Microsoft Teams (personal tab) doesn't always work on Desktop version


I have a Web app built in Vuejs and has SSO authentification using microsoftTeams.authentication.getAuthToken when running in Teams, or microsoftAuthLib when running in the browser.

Inside the company's network or when connected to the VPN everything works absolutely fine.

We recently opened it outside of the VPN and we created a public certificate for it. So when I disconnect the VPN, it works:

  • In any browser (outside of Teams).
  • Teams browser version.
  • Teams on Android/iPhone.

But it doesn't work on Teams Windows Desktop version, it fails with the following error:

Refused to display 'https://login.microsoftonline.com/.../oauth2/authorize?...' in a frame because it set 'X-Frame-Options' to 'deny'.

Anybody has an idea what could be the issue? And why would it work on the company's VPN but not outside?And only on specific cases? I am lost, any help would be appreciated.

Thank you

*** EDIT / ADDED SSO REDIRECT CODE ***

import * as microsoftTeams from "@microsoft/teams-js";
import * as microsoftAuthLib from "msal";
import settings from './settings.js';

var msalConfig = {
    auth: {
        clientId: settings.sso.id,
        authority: settings.sso.authority
    },
    cache: {
        cacheLocation: "localStorage",
        storeAuthStateInCookie: true
    }
};

var requestObj = {
    scopes: settings.sso.scopes
};

var myMSALObj = new microsoftAuthLib.UserAgentApplication(msalConfig);

myMSALObj.handleRedirectCallback(authRedirectCallBack);

function authRedirectCallBack(error, response) {

    if (error) {

        console.log(error);

    } else {

        console.log("token type is:" + response.tokenType);
    }
}

function loginRedirect(requestObj) {

    let account = myMSALObj.getAccount();

    if (!account) {

        myMSALObj.loginRedirect(requestObj);

        return false;

    } else {

        return true;
    }
}

function acquireMsalToken() {

    return new Promise(function (resolve) {

        resolve(myMSALObj.acquireTokenSilent(requestObj).then(token => {

            return token.accessToken;

        }).catch(error => {

            acquireMsalTokenRedirect(error);
        }));
    })
}

function acquireTeamsToken() {

    return new Promise((resolve, reject) => {

        microsoftTeams.authentication.getAuthToken({

            successCallback: (result) => {
                resolve(result);
            },

            failureCallback: (error) => {
                reject(error);
            }
        });
    });
}

function acquireMsalTokenRedirect(error) {

    if (error.errorCode === "consent_required" ||
        error.errorCode === "interaction_required" ||
        error.errorCode === "login_required") {

        myMSALObj.acquireTokenRedirect(requestObj);
    }
}

var msal = {

    autoSignIn: function () {

        return loginRedirect(requestObj);
    },

    acquireToken: async function () {

        if (settings.sso.inTeams) {

            microsoftTeams.initialize();
            microsoftTeams.enterFullscreen();

            return acquireTeamsToken();

        } else {

            let signedIn = msal.autoSignIn();

            if (signedIn) {

                return acquireMsalToken();
            }
        }
    }

}

export default msal

Solution

  • Replacing the acquireTeamsToken() function with the following resolved the issue.

    function acquireTeamsToken() {
    
        return new Promise((resolve, reject) => {
    
            microsoftTeams.initialize(() => {
    
                microsoftTeams.authentication.authenticate({
    
                    url: window.location.origin + "/ms-teams/auth-start",
                    width: 600,
                    height: 535,
    
                    successCallback: (result) => {
                        resolve(result);
                    },
    
                    failureCallback: (error) => {
                        reject(error);
                    }
                });
            });
        });
    }
    

    I found this documentation very helpful on how to create the Authentication pop up and how to create a Callback window with the Token in it. You might also want to cache the token and only create a popup when it expires.