在重定向uri中使用%23(#fragment)的OWIN OAuth2中间件

时间:2017-03-16 15:30:40

标签: c# asp.net oauth owin owin-middleware

我使用的是ASP.NET OWIN / Katana OAuthAuthorizationServer中间件,但遇到了麻烦。

我有一些网站试图获得授权令牌并创建了/oauth/authorize端点。但是,这些请求来自SPA(Angular),并且通常会在重定向网址中包含一个片段(#)。

发出请求后,它会将redirect_uri设置为该网址,但会对网址进行编码(因此#更改为%23)。但是,每当URL中出现%23时,状态始终设置为400,我似乎无法以任何方式阻止此操作...无法覆盖任何内容而无法覆盖Web.config保留不良角色变化等。

因此,我试图用一些占位符替换它,然后重定向回自身。这很好。但是,我似乎无法撤消我的网址更改。我需要将#重新放回URL并重定向到它,但是OWIN中间件完全忽略了任何改变URL的尝试......任何人都有任何想法?

2 个答案:

答案 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。