在 Microsoft Teams(个人选项卡)中运行的 Web 应用程序并不总是适用于桌面版本

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

我有一个在 Vuejs 中构建的 Web 应用程序,并且有 SSO 身份验证 使用 microsoftTeams.authentication.getAuthToken 当 运行 在 Teams 中,或 microsoftAuthLib 当 运行 在浏览器中。

在公司网络内或连接到 VPN 时一切正常。

我们最近在 VPN 之外打开了它,并为其创建了一个 public 证书。所以当我断开 VPN 连接时,它会起作用:

但它不适用于 Teams Windows 桌面版,它失败并出现以下错误:

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

有人知道可能是什么问题吗?为什么它可以在公司的 VPN 上运行,但不能在外部运行?而且只在特定情况下运行?我迷路了,任何帮助将不胜感激。

谢谢

*** 编辑/添加 SSO 重定向代码 ***

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

这可能是因为您在使用的任何身份验证库(希望是 MSAL 2.0)中使用身份验证弹出选项而不是重定向选项。 Teams 有点不同,因为它实际上会在必要时为您 启动一个弹出窗口 ,所以尽管听起来有点奇怪,但您实际上想要使用 redirect 选项,在启动的弹出窗口中。查看 Teams PnP 示例中的新 SSO Sample app 可能会有帮助。

  • 转到:%APPDATA%\Microsoft\Teams
  • 打开文件 hooks.json(如果不存在,请创建它)
  • 向其中添加以下内容:{"enableSso": false, "enableSsoMac": false}

就是这样,现在 Teams 桌面版具有与浏览器版本相同的身份验证工作流程。祝你有个愉快的一天。

此错误意味着您正在尝试将选项卡的 iframe 重定向到 AAD 登录流程,而 AAD 登录流程又无法为您静默生成身份验证令牌,并正在尝试显示交互式流程(例如登录或同意) :

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

为避免此问题,您需要尝试静默获取令牌,如果失败,请使用 microsoftTeams.authentication.authenticate API 打开弹出窗口 window 并在那里执行 AAD 登录流程.

用以下内容替换 acquireTeamsToken() 函数解决了问题。

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);
                }
            });
        });
    });
}

我发现此文档对如何创建身份验证弹出窗口以及如何使用其中的令牌创建回调 window 非常有帮助。 您可能还想缓存令牌并仅在其过期时创建弹出窗口。