【问题标题】:Getting an authentication token for a Microsoft Custom App获取 Microsoft 自定义应用程序的身份验证令牌
【发布时间】:2021-09-13 18:30:03
【问题描述】:

我一直在为同样的问题苦苦挣扎,我正在尝试通过 Graph-API 将文件上传到我的 MS Teams OneDrive,但我没有授权。

到目前为止,阅读文档以从 Microsoft 获取我的 Token 对我没有任何帮助,因为我是 Javascript 和 React 的新手,所以我很难让它正常工作。谁能给我一个示例,说明获取访问 Graph-API 所需的授权令牌的代码是什么样的?

我已经注册了我的 Microsoft 应用并制作了我需要的客户端密码,以便获取令牌。

提前谢谢你!

我的代码:

import React from 'react';
import './App.css';
import * as microsoftTeams from "@microsoft/teams-js";

class Tab extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      context: {}
    }
  }

  componentDidMount() {
    var myHeaders = new Headers();
    myHeaders.append("Content", "text/plain");
    myHeaders.append("Content-Type", "text/plain");
    myHeaders.append("Authorization", "Bearer {token}");

    var raw = "This works";

    var requestOptions = {
      method: 'PUT',
      headers: myHeaders,
      body: raw,
      redirect: 'follow'
    }

    fetch("https://graph.microsoft.com/v1.0/sites/OpenSesameTest/Shared%20Documents/General/FileB.txt:/", requestOptions)
          .then(response => response.text())
          .then(result => console.log(result))
          .catch(error => console.log('error', error));
  }

componentDidMount() {
    var myHeaders = new Headers();
    myHeaders.append("Content", "text/plain");
    myHeaders.append("Content-Type", "text/plain");
    myHeaders.append("Authorization", "Bearer {token}");

    var raw = "Fetch my token";

    var requestOptions = {
      method: 'POST',
      headers: myHeaders,
      body: raw,
      redirect: 'follow'
    }

    fetch("https://login.microsoftonline.com/openimstest/oauth2/v2.0/c7094fc6-9d30-429d-bb66-dd389295b426", requestOptions)
          .then(response => response.text())
          .then(result => console.log(result))
          .catch(error => console.log('error', error));
  }
  
  render() {  
      return (     
        <form>
          <div>
            <label>Select file to upload</label>
            <input type="file"></input>
          </div>
          <button type="submit">Upload</button>
        </form>     
      );
    }
  }

export default Tab;

附: 我知道我实际上并没有在我的页面上使用文件输入,但我想一开始尽可能简单,我很高兴现在通过 Graph-API 成功上传文件。 再次感谢您!

编辑: 我试图用来获取令牌的 fetch:

componentDidMount() {
    var myHeaders = new Headers();
    myHeaders.append("Content", "text/plain");
    myHeaders.append("Content-Type", "text/plain");
    myHeaders.append("Authorization", "Bearer <token>");

    var raw = "This works";

    var requestOptions = {
      method: 'GET',
      grant_type: 'Unsure where to find my client_credentials',
      client_id: 'my client-id',
      scope: 'https://graph.microsoft.com/.default',
      client_secret: 'my client-secret',
      headers: myHeaders,
      body: raw,
      redirect: 'follow'
    }

    fetch("https://login.microsoftonline.com/openimstest/oauth2/v2.0/token", requestOptions)
          .then(response => response.text())
          .then(result => console.log(result))
          .catch(error => console.log('error', error));
  }

我不确定在哪里可以找到我的 client_credentials 或放什么。我尝试使用的 fetch 可能还有其他问题。

【问题讨论】:

    标签: javascript reactjs authentication microsoft-graph-api microsoft-teams


    【解决方案1】:

    看看这个Single sign-on (SSO) support for tabs

    按照文档创建应用注册和设置公开 API 部分。

    在您的应用中为所有这些文件添加路由。对于文件夹结构,您可以使用与我在下面共享的应用程序中提到的相同的路径。

    <Route exact path="/signin" component={SignInPage} />
    <Route exact path="/signin-simple-start" component={SignInSimpleStart} />
    <Route exact path="/signin-simple-end" component={SignInSimpleEnd} />
    

    接下来看看这个文件夹结构-> signin。在这里你会看到三个文件

    1. sign-in.tsx -> 这个文件路径,需要在manifest中给出。它具有启动身份验证流程的按钮。同样仅在此文件中,您需要提供身份验证成功时要显示的页面的路由。

      successCallback: () => { history.push("/yourPage"); }

    2. sign-in-start.tsx -> 这里需要调用认证端点。因此,在我分享的应用程序中,我们有 C# 后端,从那里我们得到line 22 上的 URL 端点并将其推送到历史记录中。您可以做的是,您可以直接创建该 URL(见下文)并将其分配给变量 result(将第 22 到 24 行的代码替换为此)。

    var result = https://login.microsoftonline.com/&lt;tenant-id&gt;/oauth2/v2.0/authorize?client_id=&lt;client_id&gt;&amp;response_type=id_token token&amp;redirect_uri=https://&lt;app-domain&gt;/signin-simple-end&amp;response_mode=fragment&amp;scope=&lt;required-scope&gt;&amp;state=12345&amp;nonce=abcde&amp;login_hint=&lt;user-principal-name&gt;;

    document.location.href = result;

    1. sign-in-end.tsx -> 在这个文件中,我们得到了我们在上一步中询问的所有令牌。因此,为了获得访问令牌,您需要添加此代码

      if (hashParams["access_token"]) { localStorage.setItem("auth.result", JSON.stringify({ accessToken: hashParams["access_token"] })); }

    useEffect 中,我们正在获取其他令牌。上面的代码检查我们是否获得了 access_token 并将其设置在 localStorage 中,稍后您可以通过 localStorage.getItem("auth.result") 获得它。

    您可能需要对localStorage.getItem("auth.result") 进行少量操作才能获取令牌。

    以上方法为我们获取了委托的Graph API权限,因此您需要根据您的图表调用在您的应用中授予委托权限。

    【讨论】:

      【解决方案2】:

      Microsoft 制作了一个库,专门用于在单页应用程序中获取令牌。它被称为@azure/MSAL-browser 他们甚至专门为react做了一个包。 msal-react 这个页面显示了如何在反应中使用它的入门。这个包会为你处理令牌请求。

      没有客户端凭据流

      您可以按照以下步骤使用客户端密码执行此操作。在继续之前,请注意,您不应在 SPA Reactjs 应用程序上使用客户端凭据流,因为无法保护客户端机密。

      另一个答案应该留在这个陈述中。让我解释一下。客户端凭据流适用于在没有用户交互的情况下运行服务器端的应用程序。在客户端应用程序中使用此流程的任何人都在错误地使用它!所以我认为我们不应该教育人们如何可能滥用身份验证流程。

      【讨论】:

      • 我应该把所有这些不同的代码放在哪里?我不清楚。它们都是单独的 JS 文件吗?所有这些都在我的 Tab.js 文件中吗?我所需要的只是一个通过 Graph-API 将我的文件上传到 OneDrive 的令牌,而我需要的最后一块只是一个令牌。即使我可以在我的文件上传获取中硬编码身份验证令牌,我已经很高兴了。在这一点上,我完全不担心安全等问题。无论如何,这永远不会上线。
      • 我的反应知识不存在,但他们也创建了这个示例目录github.com/AzureAD/microsoft-authentication-library-for-js/tree/…
      【解决方案3】:

      您可以按照以下步骤使用客户端密码执行此操作。 在继续之前,请注意,您不应在 SPA Reactjs 应用程序上使用客户端凭据流,因为无法保护客户端机密。

      请注意,如果您必须在那里使用客户端密码,那么您应该将与 Graph 的交互移至服务端,然后使用其他方式保护您的应用程序,请参阅 - 此 Tutorial: Call the Microsoft Graph API in a Node.js console app 用于 Nodejs 安全守护程序服务身份验证

      用于使用 Client Secret 获取访问令牌。

      1. 在 Azure AD 上添加所需的应用程序权限,以将文件上传到 onedrive。在这种情况下Files.ReadWrite.Al。此权限需要管理员批准。

      2. 使用以下获取格式的请求从 Azure AD 获取访问令牌。

        curl --location --request GET 'https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token'
        --header '内容类型:应用程序/x-www-form-urlencoded'
        --data-urlencode 'grant_type=client_credentials'
        --data-urlencode 'client_id=client-id'
        --data-urlencode '范围=https://graph.microsoft.com/.default'
        --data-urlencode 'client_secret=client-secret'

      正如我所说,在单页 Reactjs 应用程序中使用客户端密码时将不安全。

      更好的选择是使用身份验证代码流,这在您的 SPA 案例中会更安全。按照这个来获取 reactjs Tutorial: Sign in users and call the Microsoft Graph API from a React single-page app (SPA) using auth code flow

      这将只需要:

      1. 添加 Files.ReadWrite 作为 AAD 的委派权限
      2. 以有权访问团队团队并以他们身份进行身份验证的用户登录。
      3. 致电PUT /groups/{group-id}/drive/items/{item-id}/content,其中组ID 是团队ID。

      【讨论】:

      • 您好,感谢您的回答!我已经添加了 Files.ReadWrite.All 的权限,但我正在努力让获取工作,然后在我的 POST 中使用获取的令牌。我将编辑我的原始帖子,向您展示我目前正在尝试获取的内容,但它不起作用。我确定我在做一些愚蠢的事情,但我最大的问题是格式化 fetch 以便它工作......
      • @7BitAscii - 授权类型应仅为 client_credentials。方法应该是 POST。看看这是否有效。检查您是否在控制台收到任何错误。
      • 您是否尝试过关注@Danstan Sign in users and call the Microsoft Graph API from a React分享的文档?
      • 我对这个答案投了反对票,因为没有人应该在单页应用程序中使用客户端凭据流。这是不好的做法。只需将所有有关于图形和身份验证问题的用户引导到受人尊敬的 msal 包。所以 msal-browser、msal-react 或 msal-angular
      • 这是因为您在浏览器上使用了客户端密码。 Azure 不允许这样做。正如我所建议的,您应该使用身份验证代码流。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-18
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 2017-03-10
      • 2021-12-24
      相关资源
      最近更新 更多