从 Microsoft Teams 获取 SSO 身份验证令牌时出现问题

Problem with getting SSO Auth token from Microsoft Teams

我想从 Microsoft 团队获取访问令牌,当在 postman 中使用相同的数据执行它时,它完美地工作,当在 React 应用程序中发出 post 请求时,它确实不工作。

这是我的代码:

  useEffect(() => {
    debugger;
    if (inTeams === true) {
      microsoftTeams.authentication.getAuthToken({
        successCallback: (result) => {
          console.log(result);
          const serviceRequest: any = {
            client_id: "[client_id]",
            client_secret: "[client_secret]",
            requested_token_use: "on_behalf_of",
            grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
            scope:
              "[scope]",
            assertion: result,
          };


          httpClient.GetAuthenticationToken(serviceRequest).then((res) => {
            console.log(res);

          });
          var querystring = require("querystring");
          //...
          var asd = querystring.stringify(serviceRequest);

          console.log(asd);

          axios
            .post(
              "https://login.microsoftonline.com/common/oauth2/v2.0/token",
              asd,
              {
                headers: {
                  "Content-Type": "application/x-www-form-urlencoded",
                },
              }
            )
            .then(function (response) {
              console.log(response);
            });

          microsoftTeams.appInitialization.notifySuccess();
        },
        failureCallback: function (error) {
          console.log(error);
        },
      });
    } else {
      setEntityId("Not in Microsoft Teams");
    }
  }, [inTeams]);

这是我发的(在网络上找到的,'[]'里的字段是我替换的,因为隐私)

client_id=[client_id]&client_secret=[client_secret]&requested_token_use=on_behalf_of&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&scope=[scope]&assertion=[assertion]

这是我得到的错误:

这是网络预览版: AADSTS9002326: Cross-origin token redemption is permitted only for the 'Single-Page Application' client-type.\r\nTrace ID: ef9c5d80-13d0-4001-898b-7206f4663b00\r\nCorrelation ID: 2c0d0ece-3ce5-4ee6-9cdf-8966f66cee2f\r\nTimestamp: 2022-04-01 10:06:19Z

--------------------------------

更新: 多亏了答案:)

我制作了一个获取 SSO 令牌并将其交换为 OBO 令牌的后端方法。 这是代码:

   public static async Task<string> ExchangeForOBOToken(ExchangeOBORequest request)
    {
        var contentData = new Dictionary<string, string>();
        contentData.Add("client_id", request.client_id);
        contentData.Add("client_secret", request.client_secret);
        contentData.Add("requested_token_use", request.requested_token_use);
        contentData.Add("grant_type", request.grant_type);
        contentData.Add("scope", request.scope);
        contentData.Add("assertion", request.assertion);
        
        using (var httpClient = new HttpClient())
        {
            using (var content = new FormUrlEncodedContent(contentData))
            {
                content.Headers.Clear();
                content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

                HttpResponseMessage response = await httpClient.PostAsync("https://login.microsoftonline.com/common/oauth2/v2.0/token", content);

                var res=  await response.Content.ReadAsStringAsync();
                return res;
            }
        }
        
    }

我只是从前端使用所有数据和 return OBO 令牌调用它:)

所以上面有一堆要点:

  1. 您实际上没有说明您需要令牌的用途。据推测,您希望 SSO 令牌能够调用 Graph,这就是为什么您想将其交换为“代表”(OBO) 令牌的原因 - 请确认

  2. 您不希望在您的客户端代码中进行 OBO 令牌交换 - 这只意味着在服务器端发生,这样这些宝贵的令牌就不会泄漏到攻击者。在 this video and this blog post.

    中查看更多信息
  3. 一旦您的 OBO 部分移出到您的后端,您的代码看起来会简单得多,如下所示:

  useEffect(() => {
    debugger;
    if (inTeams === true) {
      microsoftTeams.authentication.getAuthToken({
        successCallback: (result) => {
         // make your call here to your backend, which will in turn: (A) get the OBO token and (B) use it to call whatever you want on Graph.
        },
        failureCallback: function (error) {
          console.log(error);
        },
      });
    } else {
      setEntityId("Not in Microsoft Teams");
    }
  }, [inTeams]);