资源服务器中的 OwinMiddleware 实现抑制令牌验证
OwinMiddleware implementation in Resource Server suppresses Token validation
我已经设置了我的资源服务器 (Web Api 2) 来验证传入请求的 JWT 令牌。 JWT 令牌由 Auth0 颁发,我的客户端将其传递到我的网站 api。如果 Issuer、Audience 或 Expiry date 无效,这一切都可以正常工作并引发 401 响应。当我添加从 OwinMiddleware 派生的自定义中间件时,它会抑制令牌验证逻辑,并且我会收到 200 条针对无效请求的响应。
public class Startup
{
public void Configuration(IAppBuilder app)
{
var issuer = "my issuer";
var audience= "my audience";
var clientId= "my client id";
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = audience,
ValidIssuer = issuer,
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) => parameters.IssuerSigningTokens.FirstOrDefault()?.SecurityKeys?.FirstOrDefault()
},
// Setting the MetadataEndpoint so the middleware can download the RS256 certificate
MetadataEndpoint = $"{issuer.TrimEnd('/')}/wsfed/{clientId}/FederationMetadata/2007-06/FederationMetadata.xml"
});
HttpConfiguration config = new HttpConfiguration();
app.Use<HttpUsernameInjector>();
// Web API routes
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
}
}
和我的自定义 OwinMiddleWare:
public class HttpUsernameInjector : OwinMiddleware
{
public HttpUsernameInjector(OwinMiddleware next)
: base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
const string usernameClaimKey = "my username claim key";
var bearerString = context.Request.Headers["Authorization"];
if (bearerString != null && bearerString.StartsWith("Bearer ", StringComparison.InvariantCultureIgnoreCase))
{
var tokenString = bearerString.Substring(7);
var token = new JwtSecurityToken(tokenString);
var claims = token.Claims.ToList();
var username = claims.FirstOrDefault(x => x.Type == usernameClaimKey);
if (username == null) throw new Exception("Token should have username");
// Add to HttpContext
var genericPrincipal = new GenericPrincipal(new GenericIdentity(username.Value), new string[] { });
IPrincipal principal = genericPrincipal;
context.Request.User = principal;
}
await Next.Invoke(context);
}
}
我应该如何配置自定义中间件以避免 conflict/suppressing OWIN 令牌身份验证逻辑?
OWINMiddleware 没有问题,但分配 context.Request.User
会导致问题。此处创建的 GenericIdentity
具有等于 true 的只读 IsAuthenticated
,无法设置为 false
。分配 context.Request.User = genericPrincipal;
时,它会用 genericPrincipal
中的 IsAuthenticated
覆盖 context.Request.User
中的 IsAuthenticated
。需要在 Invoke 方法的开头检查身份验证结果,如果用户未通过身份验证则跳过该逻辑。所以它不会在 context.Request.User
中改变 IsAuthenticated
。
public override async Task Invoke(IOwinContext context)
{
if (context.Authentication.User.Identity.IsAuthenticated)
{
//my username injection logic
}
await Next.Invoke(context);
}
我已经设置了我的资源服务器 (Web Api 2) 来验证传入请求的 JWT 令牌。 JWT 令牌由 Auth0 颁发,我的客户端将其传递到我的网站 api。如果 Issuer、Audience 或 Expiry date 无效,这一切都可以正常工作并引发 401 响应。当我添加从 OwinMiddleware 派生的自定义中间件时,它会抑制令牌验证逻辑,并且我会收到 200 条针对无效请求的响应。
public class Startup
{
public void Configuration(IAppBuilder app)
{
var issuer = "my issuer";
var audience= "my audience";
var clientId= "my client id";
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = audience,
ValidIssuer = issuer,
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) => parameters.IssuerSigningTokens.FirstOrDefault()?.SecurityKeys?.FirstOrDefault()
},
// Setting the MetadataEndpoint so the middleware can download the RS256 certificate
MetadataEndpoint = $"{issuer.TrimEnd('/')}/wsfed/{clientId}/FederationMetadata/2007-06/FederationMetadata.xml"
});
HttpConfiguration config = new HttpConfiguration();
app.Use<HttpUsernameInjector>();
// Web API routes
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
}
}
和我的自定义 OwinMiddleWare:
public class HttpUsernameInjector : OwinMiddleware
{
public HttpUsernameInjector(OwinMiddleware next)
: base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
const string usernameClaimKey = "my username claim key";
var bearerString = context.Request.Headers["Authorization"];
if (bearerString != null && bearerString.StartsWith("Bearer ", StringComparison.InvariantCultureIgnoreCase))
{
var tokenString = bearerString.Substring(7);
var token = new JwtSecurityToken(tokenString);
var claims = token.Claims.ToList();
var username = claims.FirstOrDefault(x => x.Type == usernameClaimKey);
if (username == null) throw new Exception("Token should have username");
// Add to HttpContext
var genericPrincipal = new GenericPrincipal(new GenericIdentity(username.Value), new string[] { });
IPrincipal principal = genericPrincipal;
context.Request.User = principal;
}
await Next.Invoke(context);
}
}
我应该如何配置自定义中间件以避免 conflict/suppressing OWIN 令牌身份验证逻辑?
OWINMiddleware 没有问题,但分配 context.Request.User
会导致问题。此处创建的 GenericIdentity
具有等于 true 的只读 IsAuthenticated
,无法设置为 false
。分配 context.Request.User = genericPrincipal;
时,它会用 genericPrincipal
中的 IsAuthenticated
覆盖 context.Request.User
中的 IsAuthenticated
。需要在 Invoke 方法的开头检查身份验证结果,如果用户未通过身份验证则跳过该逻辑。所以它不会在 context.Request.User
中改变 IsAuthenticated
。
public override async Task Invoke(IOwinContext context)
{
if (context.Authentication.User.Identity.IsAuthenticated)
{
//my username injection logic
}
await Next.Invoke(context);
}