OAuth2(授权代码授予类型)的重定向 URI 中是不是应该存在动态查询参数
Posted
技术标签:
【中文标题】OAuth2(授权代码授予类型)的重定向 URI 中是不是应该存在动态查询参数【英文标题】:Should dynamic query parameters be present in the Redirection URI for an OAuth2 (Autorization Code Grant Type)OAuth2(授权代码授予类型)的重定向 URI 中是否应该存在动态查询参数 【发布时间】:2019-08-26 17:07:36 【问题描述】:诸如 Okta sponsored site 之类的来源(请参阅“按请求自定义”部分)提到,自动请求的 redirect_uri 参数绝不应该有动态查询部分(例如:用于会话匹配用途)。
引用:
服务器应拒绝任何带有重定向 URL 的授权请求 与注册的 URL 不完全匹配。
我们的 OAuth AZ 提供商是 BIG-IP F5。我们正在设置它,它们似乎符合上述观点。
我们的客户端是在别处构建的 Web 应用程序,它们似乎没有遵循上述规则。 这是授权端点的完整表示(已编辑): https://ourownF5host.ca/f5-oauth2/v1/authorize?client_id=theIDofOurClient&redirect_uri=https%3A%2F%2FourClientAppHostname%2FClientRessource%2FRessource%3FSessionId%3D76eab448-52d1-4adb-8eba-e9ec1b9432a3&state=2HY-MLB0ST34wQUPCyHM-A&scope=RessourceData&response_type=code
他们使用的 redirect_uri 格式类似于(为简单起见,我没有在此处进行 urlencode):redirect_uri=https://ourClientAppHostname/ClientRessource/Ressource?SessionId=SOMELONGSESSIONID,每次调用的 SOMELONGSESSIONID 值都不同。
我们在 RFC6749 (OAuth2) 中挖掘了 DEEP,并在第 3.1.2.2 节中找到了这一点:
授权服务器应该要求客户端提供 完整的重定向 URI(客户端可以使用“状态”请求 参数来实现每个请求的定制)。如果需要 无法注册完整的重定向 URI, 授权服务器应该要求注册 URI 方案、权限和路径(允许客户端动态变化 请求时仅重定向 URI 的查询组件 授权)。
我理解并想在此验证的是,第一个来源 Okta 和 F5 仅接受上述规则的第一部分,并要求重定向 uri 完全注册而没有任何动态部分。
我是否正确地确认他们(Okta 和 F5)不遵守摘录的第二部分,理由是他们应该“允许(ing)客户动态变化 请求时仅重定向 URI 的查询组件 授权" ?
或者,RFC6749 是否有任何形式的官方更正/演变,以保证两家公司的设计立场?
【问题讨论】:
能否请您发布您的客户端生成的完整授权请求 URI(向您的 AS 授权端点发出的请求,包含 client_id、redirect_uri、范围和 response_type)。如果需要,您可以编辑这些参数值。 @Guillaume 我尽力更新问题。请注意,我现在了解到“state”参数已从授权端点中的“redirect_uri”查询参数中正确删除。但是我最初的问题仍然代表“SessionId”参数(原始措辞中不存在,我很困惑将它们混合在一起)。请相应地更新您的答案... 我的答案仍然有效。 这就是我的想法......但由于我稍微改变了问题,我想确定一下。我很快就会颁发赏金。 (我正在与其他利益相关者讨论) 【参考方案1】:TL;DR:
不,出于安全原因,重定向 uri 必须是静态的。如果客户端需要在授权请求与其异步响应之间保留state
,请使用 OAuth 2.0 state
参数。
加长版:
RFC6749(最初的 OAuth 2.0 规范)已于 2012 年发布,从那时起 OAuth 安全形势发生了很大变化。
RFC6819, an OAuth 2.0 security review from 2013 已经提到拒绝动态制作的重定向 uri 是防止 XSS 和客户端模拟攻击的好方法。
OpenID Connect,从 2014 年开始,具有身份验证功能的 OAuth 2.0 的常用扩展,已经考虑了该建议,并要求对所有重定向 uri 进行精确的字符串匹配。
The current draft recommendation for OAuth 2.0 Best Security Practice 通过强制执行 redirect_uris 预注册并在验证请求中传递的 redirect_uri 时强制 AS 使用简单字符串比较来确认这一点。所以不能使用动态的redirect_uri。
您的客户端使用 redirect_uri 作为授权请求和响应之间的“状态保持者”,通过在 redirect_uri 中使用动态制作的SessionID
属性,肯定会做出错误的举动。 OAuth2.0 有一个专用的授权请求参数,即“state”。客户应该使用它。 AS 发出响应时会将该状态附加到 redirect_uri 的参数中,因此客户端将能够在响应中找到该状态。
正确的授权请求是:
https://youras/authorize?client_id=your_client_id&response_type=code&state=SOMELONGSTATE&redirect_uri=https%3A%2F%2Fsomehost%2Fauthcallback
响应将如下所示: https://somehost/authcallback?state=SOMELONGSTATE&code=anazcode
这样,redirect_uri 是静态的,所以一个简单的字符串比较就足以验证 AS 端的 uri。任何比简单字符串比较更复杂的算法都可能存在安全漏洞。
【讨论】:
嗨!查看问题中的网址……我的客户似乎正在使用“状态”。所以你认为我的 OAuth2 AZ 供应商应该支持这个查询参数是动态的? 据我了解,state
是 redirect_uri 的一部分,它本身就是授权请求的参数。 state
应该是授权请求的参数,redirect_uri
必须是在授权服务器上为您的特定客户端预先注册的静态。
我试图在我的回答中阐明state
参数的正确使用。
更新:客户端应用程序使用了一个 .Net 库,该库在“redirect_uri”中包含“SessionId”作为选项。他们(que client devs)更改了选项,现在严格依赖“授权端点请求”本身内的“状态”查询参数(但不在“redirect_uri”内。感谢@Guillaume!【参考方案2】:
这里似乎混淆了两件事:您引用的 URL:
https://somehost/authcallback?state=SOMELONGSTATE&scope=someobjecttype&response_type=code
建议您将客户端的重定向 URI(也称为回调 URL,如 URL 中的路径名所建议)与授权服务器的授权端点混淆。
只有授权端点会采用建议的参数,并且可能包含例如一个动态的state
值。客户端的重定向 URI 不会包含例如响应类型。
可以将redirect_uri
参数添加到授权请求中,然后必须按照您描述的方式进行匹配。确认匹配后,授权服务器将重定向回重定向URI,添加code
和state
参数。
更新(问题改变后):
OAuth 2.0 RFC6749 允许动态 (SessionId) 参数,尽管它不是最佳实践。但是,如果您的客户端是 OpenID Connect 客户端,则不允许这样做,因为 OpenID Connect 规范(OAuth 2.0 的“配置文件”)将重定向 URI 匹配为“精确”,在这种情况下,您必须配置所有可能的会话 ID。
【讨论】:
你说得对,我混合了“SessionId”(在“redirect_uri”中)和“state”......我的问题仍然代表“SessionId”(可以/应该是动态的)吗?以上是关于OAuth2(授权代码授予类型)的重定向 URI 中是不是应该存在动态查询参数的主要内容,如果未能解决你的问题,请参考以下文章
Oauth2 Instagram API“重定向 URI 与注册的重定向 URI 不匹配”
出现错误:redirect_uri_mismatch 请求中的重定向 URI:http://localhost:8080/oauth2callback 与注册的重定向 URI 不匹配
Google OAUTH:请求中的重定向URI与注册的重定向URI不匹配
redirect_uri_mismatch 请求中的重定向 URI 与授权给 OAuth 客户端的重定向 URI 不匹配