2

我正在使用 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 更改回的任何尝试...有人有什么想法吗?

4

2 回答 2

3

这是RFC 6749 第 3.1.2 节施加的限制:

端点 URI 不得包含片段组件。

基于 OAuth2 规范的 OpenID Connect 规范(以及流行的 IdentityServer3/4)似乎没有这个限制,因此您可以切换到 OIDC 或稍微改变 OAuth2 规范 :)

在 OWIN 中间件中,在OAuthAuthorizationServerHandler中检查片段的存在。

一种解决方法是通过用%23占位符替换表示片段的方式绕过此检查,并在将位置重定向标头发送到浏览器之前对其进行修补。

%23要使用占位符替换传入,您可以覆盖 providersMatchEndpoint方法:

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上。

RedirectUri一个 hacky 方法是使用反射并在 providersValidateClientRedirectUri方法中修改它:

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>
于 2018-02-22T14:15:18.793 回答
0

哈希符号https://en.wikipedia.org/wiki/Fragment_identifier之后的部分永远不会发送到服务器 - 例如,请参阅我可以在服务器端应用程序(PHP、Ruby、Python 等)上读取 URL 的哈希部分吗.)?以及许多类似的问题。

您可以做的是通过 Java 脚本在客户端对占位符进行后处理,而不是尝试重定向到带有 # 的 URL。

于 2017-03-17T11:40:02.333 回答