【问题标题】:What's wrong with this authorization exchange?这个授权交换有什么问题?
【发布时间】:2015-04-09 12:21:41
【问题描述】:

我在 Azure 网站上设置了一个带有 PluggableAuthOpenID Connect 扩展名的 MediaWiki 服务器。后者使用PHP OpenID Connect Basic Client 库。我是 Azure AD 域 example.com 的管理员,我在其中创建了一个应用程序 ID URI、登录 URL 和回复 URL 都设置为 https://wiki.azurewebsites.net/ 的应用程序。当我导航到 wiki 时,我观察到以下行为(暂时省略了 cookie 值):

  1. 客户请求

    GET https://wiki.azurewebsites.net/ HTTP/1.1

  2. RP请求

    GET https://login.windows.net/example.com/.well-known/openid-configuration

  3. IP响应

    (一些回应)

  4. RP响应

    HTTP/1.1 302 Moved Temporarily Location: https://login.windows.net/{tenant_id}/oauth2/authorize?response_type=code&redirect_uri=https%3A%2F%2Fwiki.azurewebsites.net%2F&client_id={client_id}&nonce={nonce}&state={state}

  5. 客户请求

    (跟随重定向)

  6. IP响应

    HTTP/1.1 302 Found Location: https://wiki.azurewebsites.net/?code={code}&state={state}&session_state={session_state}

  7. 客户请求

    (跟随重定向)

  8. RP请求(也重复#2 & #3)

    POST https://login.windows.net/{tenant_id}/oauth2/token grant_type=authorization_code&code={code}&redirect_uri=https%3A%2F%2Fwiki.azurewebsites.net%2F&client_id={client_id}&client_secret={client_secret}

  9. IP响应

    (由 MediaWiki 解释;我目前没有记录完整的响应)

    AADSTS50001: Resource identifier is not provided.

请注意,如果我在第 8 步中更改 OpenID PHP 客户端以提供“资源”参数,则会从 AAD 获得以下错误响应:

  1. RP请求

    POST https://login.windows.net/{tenant_id}/oauth2/token grant_type=authorization_code&code={code}&redirect_uri=https%3A%2F%2Fwiki.azurewebsites.net%2F&resource=https%3A%2F%2Fwiki.azurewebsites.net%2F&client_id={client_id}&client_secret={client_secret}

  2. IP响应

    AADSTS90027: The client '{client_id}' and resource 'https://wiki.azurewebsites.net/' identify the same application.

    (This has come up before.)

更新

根据@jricher 的建议,我已经取得了一些进展,但是在解决了几个错误之后,我遇到了一个我无法弄清楚的错误。完成这一切后,我将向受影响的库提交拉取请求。

这是我所做的:

  • 我已将第二个应用程序添加到 example.com Azure AD 域,应用程序 ID URI 设置为 mediawiki://wiki.azurewebsites.net/,作为虚拟“资源”。我还授予https://wiki.azurewebsites.net/ 应用程序对这个新应用程序的委派访问权限。

  • 在步骤 #8 中将虚拟应用程序的 URI 作为 resource 参数 传递,我现在在 #9 中取回访问、刷新和 ID 令牌!

  • OpenID Connect 库要求对 ID 令牌进行签名,但当 Azure AD 对访问令牌进行签名时,它不会对 ID 令牌进行签名。它具有以下属性:{"typ":"JWT","alg":"none"}。所以我不得不修改库以允许调用者指定未签名的 ID 令牌被视为“已验证”。呜呜呜。

  • 好的,接下来发现无法验证声明,因为我指定的 OpenID 提供程序 URL 和令牌中返回的颁发者 URL 不同。 (说真的?!)因此,必须将提供程序指定为 https://sts.windows.net/{tenant_id}/,然后才能正常工作。

  • 接下来,我发现我还没有为 OpenID Connect 扩展运行 MediaWiki DB 升级脚本。谢天谢地,这是一个快速的解决方案。

  • 在那之后,我现在剩下(我希望是)最后一个问题:尝试从 AAD 的 OpenID Connect UserInfo 端点获取用户信息。我会给出它的自己的部分。

无法获取用户信息[更新]

这就是我现在卡住的地方。在第 9 步之后,执行一两个中间请求以获取用于验证令牌的元数据和密钥,会发生以下情况:

  1. RP请求:

    (更新为使用带有Authorization: Bearer 标头的GET,根据MSDNthe spec。)

    GET https://login.windows.net/{tenant_id}/openid/userinfo Authorization: Bearer {access_token}

  2. IP响应:

    400 Bad Request AADSTS50063: Credential parsing failed. AADSTS90010: JWT tokens cannot be used with the UserInfo endpoint.

    (如果我将 #1​​0 更改为 POST 请求,正文中包含 access_token,或者查询字符串中包含 access_token 的 GET 请求,AAD 将返回错误:AADSTS70000: Authentication failed. UserInfo token is not valid. 相同如果我使用 id_token 的值代替收到的 access_token 值,就会发生这种情况。)

帮助?

更新

我仍然希望有人能够阐明最终问题(UserInfo 端点不接受不记名令牌),但我可能会将其拆分为一个单独的问题。同时,我正在向库中添加一些解决方法(即将发布的 PR),以便可以使用已经在不记名令牌中返回的声明,而不是调用 UserInfo 端点。非常感谢所有为此提供帮助的人。

我还有一个烦人的部分,想知道如果使用 OpenID Connect 基本配置文件,整个事情会不会变得更简单。我认为 MediaWiki 扩展没有实现它是有原因的。

更新 2

我刚刚遇到了a new post from Vittorio Bertocci,其中包含这个有用的提示:

...在这个请求中,应用程序正在为自己请求一个令牌!在 Azure AD 中,仅当请求的令牌是 id_token 时才有可能...

这表明,只需将步骤 8 中的令牌请求类型从 authorization_code 更改为 id_token 就可以消除对非标准 resource 参数的需求,并且还不需要丑陋的第二个 AAD 应用程序。仍然是一个 hack,但感觉不像一个。

【问题讨论】:

  • "400 Bad Request" - Microsoft 可能正在寻找作为 POST 而不是作为 GET 的请求。你需要修改 PHP 库来改变它。
  • 嗯,有趣的想法@user1949536,谢谢!
  • 好吧,不仅有趣 - 它会与所有其他请求保持一致。 :)
  • 仅供参考,我几乎可以正常工作:github.com/CyberNinjas/MW-OpenIdConnect 用户已通过身份验证并添加到用户表中。但由于某种原因,会话没有建立,我没有看到任何关于原因的错误。
  • 更正,我有它的工作。我使用的 MediaWiki 的 REL1_27 显然不稳定。如果我输入 REL1_26,我的更新代码一切正常。

标签: mediawiki azure-active-directory openid-connect


【解决方案1】:

我在 Azure 上运行它时遇到了问题,即使我在本地运行了一些东西。由于无论如何我都在尝试设置一个私有 wiki,因此我最终通过打开为整个站点启用了 Azure AD 保护:

All Settings -> Features -> Authentication / Authorization

来自https://portal.azure.com的网站内

因此,您必须先对 Azure-AD 进行身份验证,然后才能看到该站点的任何页面。一旦您通过身份验证,就会使用您的用户名为应用程序设置一组 HTTP 标头,包括 REMOTE_USER。因此,我使用以下插件将已通过身份验证的用户自动登录到 Azure:

https://www.mediawiki.org/wiki/Extension:Auth_remoteuser

【讨论】:

  • 我在这里追随你的脚步,试图找出相同的答案。与 Azure AD 对话的私有 wiki(托管在 Azure 中的 VM 上)。您的 MS-OpenIdConnect 链接已失效。可以重新发布吗?
  • @LarrySilverman 很抱歉,我似乎不再拥有该代码。我正在更新我的答案以仅引用 Auth_remoteuser。
【解决方案2】:

贾斯汀是对的。对于授权代码授予流程,您必须在授权请求或令牌请求中指定资源参数。

使用 &resource=https%3A%2F%2Fgraph.windows.net%2F 获取 Azure AD Graph API 的访问令牌。

使用 &resource=https%3A%2F%2Fmanagement.core.windows.net%2F 获取 Azure 服务管理 API 的令牌。

...

希望对你有帮助

【讨论】:

  • 谢谢!您能否提供有关为什么最后一步(#10,RP 调用/openid/userinfo 端点)失败的任何见解?那不是 Graph API,是吗?这有资源价值吗?
  • 不是。使用您在授权响应中收到的 id_token 代替访问令牌 - 如果它有效,请告诉我。
  • 那也行不通。结果与access_token 相同。
  • 我认为,如果您在授权请求中指定 scope=openid,那应该允许您取回一个 id_token 和一个访问令牌,您可以使用它来调用 userinfo 端点,而无需指定资源。让我知道这是否有效...
  • 是的,这是我直到它击中我的头脑才意识到的:Azure 在授权流程的早期发送 id_token,无需执行额外的请求。解压后的 id 令牌有我需要的东西,电子邮件和我记得的唯一标识符(现在已经是几个月前了)
【解决方案3】:

Microsoft 的 OpenID Connect(和 OAuth2)实现存在一个已知错误,需要客户端发送 resource 参数。这是一个特定于 MS 的参数,不幸的是,它破坏了与几乎所有主要 OAuth2 和 OpenID Connect 库的兼容性。我知道 MS 已经意识到了这个问题(我一直在尝试与他们的团队进行互操作性测试已经有一段时间了),但我不知道有任何解决这个问题的计划。

因此,与此同时,您唯一真正的途径是破解您的客户端软件,以便它发送一个 AS 将接受的resource 参数。看起来你设法让它发送参数,但没有发送它喜欢的值。

【讨论】:

  • 谢谢。关于该值应该是什么的任何想法?
  • 它是为了代表受保护的资源,所以它与此有关。我不知道访问通常托管在服务器本身上的身份 API 会有什么价值。
  • 嗯。我可能会尝试创建两个单独的应用程序 - 我正在考虑模拟此处描述的流程:msdn.microsoft.com/en-us/library/azure/dn645543.aspx
  • 我用尝试这种方法的结果更新了我的答案。我快搞定了,只需要让 AAD UserInfo 端点工作即可。
  • 谢谢!我很高兴有人也同意我的想法。我真的希望resource 参数是可选的:-(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 2019-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-30
相关资源
最近更新 更多