我正在使用 ASP.NET OWIN/Katana OAuthAuthorizationServer 中间件并且遇到了障碍。
我有一些站点试图获取授权令牌并创建了一个/oauth/authorize
端点。但是,这些请求来自 SPA (Angular),并且通常#
在重定向 URL 中有一个片段 ( )。
发出请求后,它会将 设置redirect_uri
为该 URL,但是 URL 编码的(因此#
更改为%23
)。但是,无论何时%23
遇到URL,状态始终设置为400,并且我似乎无法以任何方式防止这种情况……无法覆盖任何内容,也没有Web.config保留的坏字符更改,等等。
因此,我试图用一些占位符替换它,然后重定向回自身。这工作得很好。但是,我似乎无法撤消URL更改。我需要将 # 放回 URL 并重定向到该 URL,但 OWIN 中间件完全忽略了将 URL 更改回的任何尝试......有人有任何想法吗?
这是RFC 6749 第 3.1.2 节强加的限制:
端点 URI 不得包含片段组件。
建立在 OAuth2 规范之上的 OpenID Connect 规范(以及流行的 IdentityServer3/4)似乎没有这个限制,所以你可以切换到 OIDC 或稍微改变 OAuth2 规范:)
在 OWIN 中间件中,在OAuthAuthorizationServerHandler 中检查片段的存在。
解决方法是通过用%23
占位符替换表示片段并在将位置重定向标头发送到浏览器之前修补它来绕过此检查。
%23
要用占位符替换传入,您可以覆盖提供者MatchEndpoint
方法:
internal class OAuth2AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override Task MatchEndpoint(OAuthMatchEndpointContext context)
{
if (context.Request.Path.StartsWithSegments(context.Options.AuthorizeEndpointPath)
&& context.Request.QueryString.HasValue)
{
context.Request.QueryString = new QueryString(
context.Request.QueryString.Value.Replace("%23", "__fragment__"));
}
return base.MatchEndpoint(context);
}
}
另一部分更棘手,因为默认情况下您似乎无法从提供程序类中执行此操作,因为redirectUri
它内部保留在OAuthValidateClientRedirectUriContext 上。
一个hacky方法是使用反射并RedirectUri
在提供者ValidateClientRedirectUri
方法中修改它:
public override async Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
// Test if the redirect uri is allowed, if not call context.SetError("invalid_client");
var redirectUri = context.RedirectUri.Replace("__fragment__", "#");
var setter = context.GetType().GetProperty(nameof(context.RedirectUri))?.GetSetMethod(true);
setter?.Invoke(context, new[] { redirectUri });
context.Validated(redirectUri);
}
另一种方法是向链中添加一个简单的中间件(在 OAuth2 中间件之前),它监视响应(因此在等待下一个中间件之后)并在需要的地方修补 Location 标头。这不像设置私有属性那么棘手,但现在补丁分布在 2 个不同的地方,这不太容易维护。
通过上述解决方法,重定向 URI 如下所示
https://server.com/#spa/path/123
请注意,您会将 URL 编码版本传递给授权端点 redirect_uri 参数
将导致重定向到
https://server.com/#spa/path/123&access_token=<the_access_token>
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句