我使用的是ASP.NET OWIN / Katana OAuthAuthorizationServer中间件,但遇到了麻烦。
我有一些网站试图获得授权令牌并创建了/oauth/authorize
端点。但是,这些请求来自SPA(Angular),并且通常会在重定向网址中包含一个片段(#
)。
发出请求后,它会将redirect_uri
设置为该网址,但会对网址进行编码(因此#
更改为%23
)。但是,每当URL中出现%23
时,状态始终设置为400,我似乎无法以任何方式阻止此操作...无法覆盖任何内容而无法覆盖Web.config保留不良角色变化等。
因此,我试图用一些占位符替换它,然后重定向回自身。这很好。但是,我似乎无法撤消我的网址更改。我需要将#重新放回URL并重定向到它,但是OWIN中间件完全忽略了任何改变URL的尝试......任何人都有任何想法?
答案 0 :(得分:1)
这是RFC 6749 Section 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 param
将导致重定向到
https://server.com/#spa/path/123&access_token=<the_access_token>
答案 1 :(得分:0)
哈希标志https://en.wikipedia.org/wiki/Fragment_identifier之后的部分永远不会被发送到服务器 - 请参阅例如Can I read the hash portion of the URL on my server-side application (PHP, Ruby, Python, etc.)?以及此处的许多类似问题。
您可以做的是通过Java Script在客户端对posthodler进行后期处理,而不是尝试使用#重定向到URL。