如何正确注册和访问 OAuth2 的 Office 365 Graph API(使用来自 Ruby 的 omniauth)?

How to properly register and access Office 365 Graph API for OAuth2 (using omniauth from Ruby)?

我正在尝试从 Ruby on Rails 应用程序(特别是日历读取 API)访问 Office 365(图表 API)。我们正在为我们的 OAuth2 流程使用 omniauth,因此,我们还尝试使用 omniauth-office365 and the omniauth-microsoft-office365 gem 访问图表 API。但到目前为止,我还无法使用这两个 gem 获得访问令牌。

我已经在 Application Registration Portal, but any time I wanted to get Calendars.Read permission (using scope "profile https://graph.microsoft.com/calendar.read" 中注册了我们的应用程序,我总是收到错误 AADSTS65005: The client application has requested access to resource 'https://graph.windows.net/'. This request has failed because the client has not specified this resource in its requiredResourceAccess list。阅读更多关于此的文章,我觉得我需要实际通过 Azure AD ,所以我注册了。但似乎我必须在 Azure 仪表板中注册一个全新的 Web 应用程序,该应用程序没有 link 到以前创建的应用程序。我试了一下,但这只会导致AADSTS70002: Error validating credentials. AADSTS50011: The reply address 'https://example.com/auth/office365/callback?code=AQABA...a_very_long_string&session_state=e1029a3b-f6a5-4e7a-940e-18a21ee4c44f' does not match the reply address 'https://example.com/auth/office365/callback' provided when requesting Authorization code. 错误。

我正处于完全困惑的地步。解决这个问题并让它发挥作用的正确方法是什么?我不可能真的需要通过 Azure AD,对吧?那么申请注册门户的意义何在?如果有人能阐明一些观点,那就太好了...

谢谢,帕斯卡

Office 365API和Azure AD的关系是Azure AD作为授权服务器,Office 365API是在Azure AD注册的资源服务器

按照这些步骤让您的应用正常运行

  1. 使用您的任一方式登录 Microsoft 应用程序注册门户 个人或工作或学校帐户。
  2. 选择添加应用。
  3. 输入应用程序的名称,然后选择创建应用程序。 显示注册页面,列出您的应用程序的属性。
  4. 复制应用程序 ID。这是您的应用程序的唯一标识符。
  5. 在“应用程序机密”下,选择“生成新密码”。复制 来自“新密码生成”对话框的应用程序机密。
  6. 您将使用应用程序 ID 和应用程序密码来配置应用程序。
  7. 在“平台”下,选择“添加平台”>“Web”。 确保选中允许隐式流复选框,然后输入 http://localhost:3000/auth/microsoft_v2_auth/callback 作为重定向 URI。 Allow Implicit Flow 选项启用 OpenID Connect 混合流。在身份验证期间,这使应用程序能够接收登录信息 (id_token) 和应用程序用来获取访问令牌的工件(在本例中为授权代码)。 重定向 URI http://localhost:3000/auth/microsoft_v2_auth/callback 是 OmniAuth 中间件在处理身份验证请求后配置使用的值。
  8. 选择保存。

您可能会发现 interesting. Also a working example of Accessing graph API in Rails here

好吧,折腾了好久,终于搞定了。而且 有这么多不同的方法可以访问不同的 API,每个方法都有自己的特定版本,每个方法都有一大堆过时的 "this is how you do it"篇。

让我总结一下我是如何让一切正常工作的,以及我学到的经验教训。

  1. 有一个 "old way" 和一个 "new way" 可以访问 API。旧方法 (v1.0) 涉及 Azure AD,您必须在其中获取 Azure 帐户并在该仪表板中配置所有内容。新方法 (v2.0) 涉及 Application Registration Portal and just that. Also see this article.
  2. Graph API 版本当前仍为 v1.0,此版本号与上述身份验证 (Azure AD) 版本号无任何关系。 (另见 this article
  3. 我正在使用 omniauth-office365 and the omniauth-microsoft-office365 gems, both of which are trying to access the resources at the host https://outlook.office.com/, whereas all examples refer to base https://graph.microsoft.com. Switching to the microsoft_v2_auth gem included in this Ruby sample 让我更进一步。
  4. AADSTS65005 似乎与范围的确切 "wording" 有关。我见过像 :scope => 'openid email profile offline_access https://graph.microsoft.com/calendar.read' 这样的措辞,但正确的措辞是 :scope => 'openid email profile offline_access https://graph.microsoft.com/Calendars.Read'(所以复数 Calendars 和 Pascal 大小写)。这似乎为我解决了问题。
  5. "Insufficient privileges to complete the operation." 发生在使用访问令牌成功回调之后,但就在 gem 想要从 /v1.0/me API 获取额外的配置文件信息时。只有在我将 https://graph.microsoft.com/User.Read 添加到我的 Ruby 应用程序的范围以及在应用程序注册中授予 User.Read 之后,gem 似乎具有所需的权限并且错误消失了。 注意!更新您的应用程序配置似乎最多需要 30 分钟才能生效!这使得 该死的 很难取得任何进展,也很难确切地找到什么动作有什么效果。
  6. Microsoft 访问令牌将在一小时内过期,因此您需要经常使用刷新令牌刷新访问令牌。仅当您在范围内包含 offline_access 时,您才会通过初始授权请求获得刷新令牌(请参阅第 4 点)。然后你可以使用以下类型的代码:

    oauth = OmniAuth::Strategies::MicrosoftV2Auth.new(
      nil, 
      ENV['OFFICE365_KEY'], 
      ENV['OFFICE365_SECRET'] 
    )
    token = OAuth2::AccessToken.new(
      oauth.client, 
      @access_token, 
      { refresh_token: @refresh_token }
    )
    new_token = token.refresh!
    @access_token = new_token.token if new_token.token
    

此外,在测试时,撤销您在早期测试中获得的访问令牌非常重要。这可以在 myapps.microsoft.com.

完成

我在这个过程中也 运行 遇到过 CSRF 错误,在这种情况下,您需要清除缓存。

如果我发现任何其他有趣的东西,我会把它添加到这里,希望没有人不得不在这些阴暗的 API 森林中徘徊太久。 :(