Microsoft Teams React-App SSO not working on iOS mobile

177 views Asked by At

I am creating a react app for teams. Using the teams-toolkit i added SSO as instructed in their doku. Everything works fine, i can login users and get accessTokens to call my secured BE. But for some reason the SSO does not work on iOS mobile devices. The Pop-Up just seems to not load or doesn't do anything resolving in an UiRequirredError when calling useGraph to acces user information. I've tried to research this and it seems that this is a known bug for the teamsfx library and it is recommended to use OBO for this situation instead, but im not sure how to do this, especially because my BE is secured via App Service and needs accessTokens to handle requests. So how am i supposed to handle OBO flow?

My 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>

My 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>

This is how i call 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 }
    );

Everything is pretty much as its set in the doku and as i said it works fine everywhere except for iOS. Could this maybe just be a problem with Pop-up blockers in iOS? If so how can i enable pop-ups in Microsoft teams so that my app can use them?

0

There are 0 answers