You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Microsoft Teams React应用iOS端SSO失效及OBO流实现咨询

问题:Teams Toolkit开发的React应用iOS移动端SSO失效及OBO流适配疑问

我使用Teams Toolkit开发Microsoft Teams React应用,已按照官方文档配置SSO功能,在非iOS设备上可正常完成用户登录并获取accessToken调用受保护的App Service后端。但iOS移动端的SSO功能失效:登录弹窗无法加载,调用useGraph接口获取用户信息时触发UiRequirredError。

经排查发现这是TeamsFx库的已知Bug,官方建议改用OBO流解决,但我不清楚如何适配依赖accessToken的App Service后端实现该流程。此外,我怀疑是否是iOS弹窗拦截导致问题,想了解如何在Microsoft Teams中启用弹窗权限。

以下是相关代码:

auth-start.html

<html>
  <head>
    <title>Login Start Page</title>
    <meta charset="utf-8" />
  </head>

  <body>
  <script src="https://res.cdn.office.net/teams-js/2.7.1/js/MicrosoftTeams.min.js" integrity="sha384-4Gy2G+qxzDVdrdemcVqKVQvaSK1Ghg3x6xcsaMLPc/pw7KPtiogHGM97LTWF2PWg" crossorigin="anonymous"></script>
    <script
      type="text/javascript"
      src="https://alcdn.msauth.net/browser/2.21.0/js/msal-browser.min.js"
      integrity="sha384-s/NxjjAgw1QgpDhOlVjTceLl4axrp5nqpUbCPOEQy1PqbFit9On6uw2XmEF1eq0s"
      crossorigin="anonymous">
    </script>
    <script type="text/javascript">
      microsoftTeams.app.initialize().then(() => {
        microsoftTeams.app.getContext().then(async (context) => {
          // Generate random state string and store it, so we can verify it in the callback
          var currentURL = new URL(window.location);
          var clientId = currentURL.searchParams.get("clientId");
          var scope = currentURL.searchParams.get("scope");
          var loginHint = currentURL.searchParams.get("loginHint");

          const msalConfig = {
            auth: {
              clientId: clientId,
              authority: `https://login.microsoftonline.com/${context.user.tenant.id}`,
              navigateToLoginRequestUrl: false,
            },
            cache: {
              cacheLocation: "localStorage",
            },
          }

          const msalInstance = new msal.PublicClientApplication(msalConfig);
          const scopesRequest = {
            scopes: ["User.Read", 'scope for my BE', "profile", "User.ReadBasic.All"],
            redirectUri: window.location.origin + `/auth-end.html?clientId=${clientId}`,
            loginHint: loginHint
          };
          await msalInstance.loginPopup(scopesRequest);
        });
      });
      </script>
  </body>
</html>

auth-end.html

<html>
  <head>
    <title>Login End Page</title>
    <meta charset="utf-8" />
  </head>

  <body>
  <script src="https://res.cdn.office.net/teams-js/2.7.1/js/MicrosoftTeams.min.js" integrity="sha384-4Gy2G+qxzDVdrdemcVqKVQvaSK1Ghg3x6xcsaMLPc/pw7KPtiogHGM97LTWF2PWg" crossorigin="anonymous"></script>
    <script
      type="text/javascript"
      src="https://alcdn.msauth.net/browser/2.21.0/js/msal-browser.min.js"
      integrity="sha384-s/NxjjAgw1QgpDhOlVjTceLl4axrp5nqpUbCPOEQy1PqbFit9On6uw2XmEF1eq0s"
      crossorigin="anonymous">
    </script>
    <script type="text/javascript">
      var currentURL = new URL(window.location);
      var clientId = currentURL.searchParams.get("clientId");

      microsoftTeams.app.initialize().then(() => {
        microsoftTeams.app.getContext().then(async (context) => {
          const msalConfig = {
            auth: {
              clientId: clientId,
              authority: `https://login.microsoftonline.com/${context.user.tenant.id}`,
              navigateToLoginRequestUrl: false
            },
            cache: {
              cacheLocation: "sessionStorage",
            },
          }

          const msalInstance = new window.msal.PublicClientApplication(msalConfig);
          msalInstance.handleRedirectPromise()
            .then((tokenResponse) => {
              if (tokenResponse !== null) {
                microsoftTeams.authentication.notifySuccess(JSON.stringify({
                  sessionStorage: localStorage
                }));
              } else {
                microsoftTeams.authentication.notifyFailure("Get empty response.");
              }
            })
            .catch((error) => {
              microsoftTeams.authentication.notifyFailure(JSON.stringify(error));
            });
        });
      });
    </script>
  </body>
</html>

useGraph调用代码

// For usage of useGraph(), please refer to: https://www.npmjs.com/package/@microsoft/teamsfx-react#usegraph.
const { loading, error, data, reload } = useGraph(
    async (graph, teamsfx, scope) => {
        // Call graph api use `graph` instance to get user profile information
        let profileData;
        try {
            profileData = await graph.api("/me").get();
        } catch (error) {
            setError(error)
        }

        //Get initial token to identify if user roles
        const credential = teamsfx.getCredential()
        const accessToken = await credential.getToken(["profile", BE_SCOPE_STRING]);


        const currentUser = new User(profileData.id, profileData.displayName);
        return { profileData, currentUser, accessToken };
    },
    { scope: ["User.Read", BE_SCOPE_STRING, "profile", "User.ReadBasic.All"], teamsfx: teamsfx }
);

内容的提问来源于stack exchange,提问作者civlon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 13:22:34