OWIN OAuth2 中间件在重定向 uri 中带有 %23(# 片段)
OWIN OAuth2 middleware with %23 (# fragment) in redirect uri
我正在使用 ASP.NET OWIN/Katana OAuthAuthorizationServer 中间件,运行 遇到了麻烦。
我有一些站点试图获取授权令牌并创建了一个 /oauth/authorize
端点。但是,这些请求来自 SPA (Angular),并且在重定向 URL.
中通常会有一个片段 (#
)
发出请求时,它会将 redirect_uri
设置为 URL,但 URL 编码(因此 #
更改为 %23
).但是,每当 %23
在 URL 中出现时,状态总是设置为 400,我似乎无法以任何方式阻止这种情况......无法覆盖任何东西并且没有 Web.config保留坏字符修改等
因此,我试图用一些占位符替换它,然后重定向回它自己。这很好用。但是,我似乎无法撤消我的 URL 更改。我需要将 # 放回 URL 并重定向到那里,但是 OWIN 中间件完全忽略了将 URL 改回去的任何尝试...有人有任何想法吗?
井号后的部分 https://en.wikipedia.org/wiki/Fragment_identifier never to be sent to server - see for example Can I read the hash portion of the URL on my server-side application (PHP, Ruby, Python, etc.)? 以及此处的许多类似问题。
您可以做的是 post 通过 Java 脚本在客户端处理您的 placehodler,而不是尝试使用其中的 # 重定向到 URL。
这是 RFC 6749 Section 3.1.2 施加的限制:
The endpoint URI MUST NOT include a fragment component.
基于 OAuth2 规范的 OpenID Connect 规范(以及流行的 IdentityServer3/4)似乎没有此限制,因此您可以切换到 OIDC 或稍微改变 OAuth2 规范:)
在 OWIN 中间件中,片段的存在在 OAuthAuthorizationServerHandler 中检查。
A work-around 是通过用占位符替换表示片段的 %23
来绕过此检查,并在发送到浏览器之前修补位置重定向 header。
要用占位符替换传入的 %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);
}
}
另一部分比较棘手,因为您似乎无法从提供程序 class 默认情况下执行此操作,因为 redirectUri
在内部保存在 OAuthValidateClientRedirectUriContext.
一种 hacky 方法是使用反射并在提供程序 ValidateClientRedirectUri
方法中修改此 RedirectUri
:
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 中间件之前)以监视响应(因此在等待下一个中间件之后)并在需要时修补位置 header。这比设置私有 属性 更简单,但现在补丁分布在 2 个不同的地方,难以维护。
上面 work-around 一个像
这样的重定向 URI
https://server.com/#spa/path/123
请注意,您会将 URL-encoded 版本传递给授权端点 redirect_uri param
将重定向到
https://server.com/#spa/path/123&access_token=<the_access_token>
我正在使用 ASP.NET OWIN/Katana OAuthAuthorizationServer 中间件,运行 遇到了麻烦。
我有一些站点试图获取授权令牌并创建了一个 /oauth/authorize
端点。但是,这些请求来自 SPA (Angular),并且在重定向 URL.
#
)
发出请求时,它会将 redirect_uri
设置为 URL,但 URL 编码(因此 #
更改为 %23
).但是,每当 %23
在 URL 中出现时,状态总是设置为 400,我似乎无法以任何方式阻止这种情况......无法覆盖任何东西并且没有 Web.config保留坏字符修改等
因此,我试图用一些占位符替换它,然后重定向回它自己。这很好用。但是,我似乎无法撤消我的 URL 更改。我需要将 # 放回 URL 并重定向到那里,但是 OWIN 中间件完全忽略了将 URL 改回去的任何尝试...有人有任何想法吗?
井号后的部分 https://en.wikipedia.org/wiki/Fragment_identifier never to be sent to server - see for example Can I read the hash portion of the URL on my server-side application (PHP, Ruby, Python, etc.)? 以及此处的许多类似问题。
您可以做的是 post 通过 Java 脚本在客户端处理您的 placehodler,而不是尝试使用其中的 # 重定向到 URL。
这是 RFC 6749 Section 3.1.2 施加的限制:
The endpoint URI MUST NOT include a fragment component.
基于 OAuth2 规范的 OpenID Connect 规范(以及流行的 IdentityServer3/4)似乎没有此限制,因此您可以切换到 OIDC 或稍微改变 OAuth2 规范:)
在 OWIN 中间件中,片段的存在在 OAuthAuthorizationServerHandler 中检查。
A work-around 是通过用占位符替换表示片段的 %23
来绕过此检查,并在发送到浏览器之前修补位置重定向 header。
要用占位符替换传入的 %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);
}
}
另一部分比较棘手,因为您似乎无法从提供程序 class 默认情况下执行此操作,因为 redirectUri
在内部保存在 OAuthValidateClientRedirectUriContext.
一种 hacky 方法是使用反射并在提供程序 ValidateClientRedirectUri
方法中修改此 RedirectUri
:
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 中间件之前)以监视响应(因此在等待下一个中间件之后)并在需要时修补位置 header。这比设置私有 属性 更简单,但现在补丁分布在 2 个不同的地方,难以维护。
上面 work-around 一个像
这样的重定向 URIhttps://server.com/#spa/path/123
请注意,您会将 URL-encoded 版本传递给授权端点 redirect_uri param
将重定向到
https://server.com/#spa/path/123&access_token=<the_access_token>