我已经使用PluggableAuth和OpenID Connect扩展在 Azure 网站上设置了一个 MediaWiki 服务器。后者使用PHP OpenID Connect Basic Client库。我是 Azure AD 域的管理员,example.com
我在其中创建了一个应用程序 ID URI、登录 URL 和回复 URL 都设置为https://wiki.azurewebsites.net/
. 当我导航到 wiki 时,我观察到以下行为(暂时省略 cookie 值):
客户要求
GET https://wiki.azurewebsites.net/ HTTP/1.1
RP请求
GET https://login.windows.net/example.com/.well-known/openid-configuration
IP响应
(一些回应)
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}
客户要求
(跟随重定向)
IP响应
HTTP/1.1 302 Found Location: https://wiki.azurewebsites.net/?code={code}&state={state}&session_state={session_state}
客户要求
(跟随重定向)
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}
IP响应
(由 MediaWiki 解释;我此时没有记录完整的响应)
AADSTS50001: Resource identifier is not provided.
请注意,如果我在步骤 8 中更改 OpenID PHP 客户端以提供“资源”参数,则会从 AAD 获得以下错误响应:
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}
IP响应
AADSTS90027: The client '{client_id}' and resource 'https://wiki.azurewebsites.net/' identify the same application.
更新
根据@jricher 的建议,我已经取得了一些进展,但是在解决了更多错误之后,我遇到了一个我无法弄清楚的错误。完成这一切后,我将向受影响的库提交拉取请求。
这是我所做的:
我已将第二个应用程序添加到
example.com
Azure AD 域,并将 App ID URI 设置为mediawiki://wiki.azurewebsites.net/
,作为虚拟“资源”。我还授予https://wiki.azurewebsites.net/
应用程序对这个新应用程序的委托访问权限。在步骤 #8中将
resource
虚拟应用程序的 URI 作为参数传递,我现在在 #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 步之后,在一个或两个中间请求获取元数据和用于验证令牌的密钥之后,会发生以下情况:
RP请求:
(更新为使用带有
Authorization: Bearer
标头的 GET,根据MSDN和规范。)GET https://login.windows.net/{tenant_id}/openid/userinfo Authorization: Bearer {access_token}
知识产权回应:
400 Bad Request AADSTS50063: Credential parsing failed. AADSTS90010: JWT tokens cannot be used with the UserInfo endpoint.
(如果我将 #10 更改
access_token
为正文中的 POST 请求或查询字符串中的 GET 请求access_token
,AAD 将返回错误:如果AADSTS70000: Authentication failed. UserInfo token is not valid.
我使用已收到。)id_token
access_token
帮助?
更新
我仍然希望有人能阐明最后一个问题(UserInfo 端点不接受承载令牌),但我可能会将其拆分为一个单独的问题。同时,我正在向库中添加一些解决方法(即将发布的 PR),以便可以使用已经在不记名令牌中返回的声明,而不是调用 UserInfo 端点。非常感谢所有为此提供帮助的人。
我还有一个唠叨的部分想知道如果使用 OpenID Connect 基本配置文件,整个事情是否会变得更简单。我认为 MediaWiki 扩展没有实现它是有原因的。
更新 2
我刚刚看到Vittorio Bertocci 的一篇新帖子,其中包含了这个有用的提示:
...在此请求中,应用程序正在为自己请求令牌!在 Azure AD 中,仅当请求的令牌是 id_token 时才有可能...
这表明只需将步骤 8 中的令牌请求类型从authorization_code
更改为id_token
即可消除对非标准resource
参数的需求,并且也使丑陋的第二个 AAD 应用程序变得不必要。仍然是一个黑客,但感觉不像一个黑客。