在 Microsoft.Owin.Security.OpenIdConnect 中间件的响应中添加位置 header
Adding location header on response from Microsoft.Owin.Security.OpenIdConnect middleware
我们已经使用 IndentityServer 和 Owin 自托管网站 API 实现了 OAuth。每当客户端尝试访问我们经过身份验证的端点时,我们都会使用 Microsoft.Owin.Security.OpenIdConnect 中间件来拦截并将调用重定向到 IndentityServer 以进行身份验证。在 API 调用的情况下,我们不希望 return 302,而是具有位置 header 和 IdentityServer 的 url 的 401。我们可以通过设置
将 OWIN 中间件设置为 return 401
AuthenticationMode = AuthenticationMode.Passive
但我们无法添加位置 header。我们如何做到这一点?我们已尝试设置 header(请参阅下面的代码),但它不起作用。似乎响应是由中间件在内部构建的。
appBuilder.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = idSrvUri.ToString(),
AuthenticationType = WebServiceConstants.OAuthAuthType,
ClientId = "beocloud",
Scope = "openid profile roles",
ResponseType = "id_token token",
AuthenticationMode = AuthenticationMode.Passive,
SignInAsAuthenticationType = WebServiceConstants.OAuthAuthType,
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.AuthenticationRequest)
{
n.ProtocolMessage.RedirectUri = n.Request.Scheme + "://" + n.Request.Host + "/";
n.Response.Headers.Add("Location", new []{n.ProtocolMessage.CreateAuthenticationRequestUrl()});
}
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
}
return Task.FromResult(0);
}
}
});
}
这是在您的 MVC 代码旁边托管 Web API 的问题——您在 API 端使用了错误的安全中间件。 OIDC 中间件假定 HTTP 调用来自它可以重定向的浏览器 window。
我建议将您的 API 拆分为单独的主机和管道,并使用基于令牌的安全架构和中间件。我们在 github 存储库中有很多这种模式的样本。
我们已经使用 IndentityServer 和 Owin 自托管网站 API 实现了 OAuth。每当客户端尝试访问我们经过身份验证的端点时,我们都会使用 Microsoft.Owin.Security.OpenIdConnect 中间件来拦截并将调用重定向到 IndentityServer 以进行身份验证。在 API 调用的情况下,我们不希望 return 302,而是具有位置 header 和 IdentityServer 的 url 的 401。我们可以通过设置
将 OWIN 中间件设置为 return 401AuthenticationMode = AuthenticationMode.Passive
但我们无法添加位置 header。我们如何做到这一点?我们已尝试设置 header(请参阅下面的代码),但它不起作用。似乎响应是由中间件在内部构建的。
appBuilder.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = idSrvUri.ToString(),
AuthenticationType = WebServiceConstants.OAuthAuthType,
ClientId = "beocloud",
Scope = "openid profile roles",
ResponseType = "id_token token",
AuthenticationMode = AuthenticationMode.Passive,
SignInAsAuthenticationType = WebServiceConstants.OAuthAuthType,
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.AuthenticationRequest)
{
n.ProtocolMessage.RedirectUri = n.Request.Scheme + "://" + n.Request.Host + "/";
n.Response.Headers.Add("Location", new []{n.ProtocolMessage.CreateAuthenticationRequestUrl()});
}
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
}
return Task.FromResult(0);
}
}
});
}
这是在您的 MVC 代码旁边托管 Web API 的问题——您在 API 端使用了错误的安全中间件。 OIDC 中间件假定 HTTP 调用来自它可以重定向的浏览器 window。
我建议将您的 API 拆分为单独的主机和管道,并使用基于令牌的安全架构和中间件。我们在 github 存储库中有很多这种模式的样本。