使用 OWIN 将 Web Api 2 配置为资源服务器
Configuring Web Api 2 as Resource Server using OWIN
正在尝试将我的 Web Api 配置为资源服务器。我的客户端登录 Auth0 并获取 Bearer 令牌,因此授权服务器是 Auth0 而不是我的 Api。然后他们将请求连同 Bearer 令牌一起发送到我的 Api。在我的 ASP.Net Web Api 中,我在 Startup class 中实施了以下 OWIN 配置,以验证 Auth0 按照指示发出的请求 JWT Bearer 令牌 here。
状态:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var auth0Options = new Auth0Options()
{
Issuer = $"https://{ConfigurationManager.AppSettings["Auth0ApiInternalDomain"]}/",
Audience = ConfigurationManager.AppSettings["Auth0ApiInternalAudience"],
ClientId = ConfigurationManager.AppSettings["Auth0ApiInternalClientID"]
};
Auth0Config.Configure(app, auth0Options);
// Configure Web API
WebApiConfig.Configure(app);
}
}
和 Auth0Config class:
public class Auth0Config
{
public static void Configure(IAppBuilder app, Auth0Options options)
{
if (options == null)
throw new ArgumentNullException(nameof(options));
var keyResolver = new OpenIdConnectSigningKeyResolver(options.Issuer);
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = options.Audience,
ValidIssuer = options.Issuer,
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) => keyResolver.GetSigningKey(identifier),
ValidateLifetime = true,
ValidateIssuer = true,
ValidateAudience = true,
LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) =>
{
if (expires.Value < DateTime.UtcNow)
{
return false;
}
return true;
}
}
});
}
}
我将 app.config 中的 Audience、Issuer 和 CliedntId 传递给此方法。我的目的是弄清楚从客户端到我的 Api 的 Bearer 令牌是否有效(这里作为第一步我需要验证到期日期)。当我为传入请求调试我的代码时,LifetimeValidator 工作正常,returns false 对于过期的令牌。我用 [Authorize] 修饰了我的操作,并期望得到 401 错误,但实际响应是 200,它似乎忽略了 LifetimeValidator 实现。
我的操作:
[Authorize]
public IHttpActionResult Get(string id)
{
var result = _bookingService.GetBooking(id);
if (result == null) return NotFound();
return Ok(result);
}
- 我是否遗漏了一些正确的东西?
- 这是验证令牌过期的好方法吗?
- 是否可以仅使用 OWIN 来验证从 Web api 应用程序发出的请求 Bearer 令牌?
原来 OwinMiddleware class 的 Invoke 方法已在我的应用程序中被覆盖,以从令牌中查找用户名并将其注入 Request.User
。不知道为什么,但它以某种方式忽略了 OWIN 令牌验证功能,并且没有检查受众、发行者或过期时间。
public static void Configure(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
app.Use<HttpUsernameInjector>();
app.UseWebApi(config);
}
public class HttpUsernameInjector : OwinMiddleware
{
public HttpUsernameInjector(OwinMiddleware next)
: base(next){}
public override async Task Invoke(IOwinContext context)
{
const string usernameClaimKey = "myUserNameClaimKey";
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);
}
}
通过删除此 class,OWIN 令牌验证工作正常!
- 根据我的研究,Web Api 中最好的令牌验证方法是 OWIN 和 IAuthenticationFilter.
- 有可能,因为资源服务器和授权服务器是解耦的。可以找到更多信息 here
更新
找到解决方案 以阻止 OwinMiddleware 抑制我的令牌验证逻辑
正在尝试将我的 Web Api 配置为资源服务器。我的客户端登录 Auth0 并获取 Bearer 令牌,因此授权服务器是 Auth0 而不是我的 Api。然后他们将请求连同 Bearer 令牌一起发送到我的 Api。在我的 ASP.Net Web Api 中,我在 Startup class 中实施了以下 OWIN 配置,以验证 Auth0 按照指示发出的请求 JWT Bearer 令牌 here。
状态:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var auth0Options = new Auth0Options()
{
Issuer = $"https://{ConfigurationManager.AppSettings["Auth0ApiInternalDomain"]}/",
Audience = ConfigurationManager.AppSettings["Auth0ApiInternalAudience"],
ClientId = ConfigurationManager.AppSettings["Auth0ApiInternalClientID"]
};
Auth0Config.Configure(app, auth0Options);
// Configure Web API
WebApiConfig.Configure(app);
}
}
和 Auth0Config class:
public class Auth0Config
{
public static void Configure(IAppBuilder app, Auth0Options options)
{
if (options == null)
throw new ArgumentNullException(nameof(options));
var keyResolver = new OpenIdConnectSigningKeyResolver(options.Issuer);
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = options.Audience,
ValidIssuer = options.Issuer,
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) => keyResolver.GetSigningKey(identifier),
ValidateLifetime = true,
ValidateIssuer = true,
ValidateAudience = true,
LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) =>
{
if (expires.Value < DateTime.UtcNow)
{
return false;
}
return true;
}
}
});
}
}
我将 app.config 中的 Audience、Issuer 和 CliedntId 传递给此方法。我的目的是弄清楚从客户端到我的 Api 的 Bearer 令牌是否有效(这里作为第一步我需要验证到期日期)。当我为传入请求调试我的代码时,LifetimeValidator 工作正常,returns false 对于过期的令牌。我用 [Authorize] 修饰了我的操作,并期望得到 401 错误,但实际响应是 200,它似乎忽略了 LifetimeValidator 实现。
我的操作:
[Authorize]
public IHttpActionResult Get(string id)
{
var result = _bookingService.GetBooking(id);
if (result == null) return NotFound();
return Ok(result);
}
- 我是否遗漏了一些正确的东西?
- 这是验证令牌过期的好方法吗?
- 是否可以仅使用 OWIN 来验证从 Web api 应用程序发出的请求 Bearer 令牌?
原来 OwinMiddleware class 的 Invoke 方法已在我的应用程序中被覆盖,以从令牌中查找用户名并将其注入
Request.User
。不知道为什么,但它以某种方式忽略了 OWIN 令牌验证功能,并且没有检查受众、发行者或过期时间。public static void Configure(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); app.Use<HttpUsernameInjector>(); app.UseWebApi(config); } public class HttpUsernameInjector : OwinMiddleware { public HttpUsernameInjector(OwinMiddleware next) : base(next){} public override async Task Invoke(IOwinContext context) { const string usernameClaimKey = "myUserNameClaimKey"; 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); } }
通过删除此 class,OWIN 令牌验证工作正常!
- 根据我的研究,Web Api 中最好的令牌验证方法是 OWIN 和 IAuthenticationFilter.
- 有可能,因为资源服务器和授权服务器是解耦的。可以找到更多信息 here
更新
找到解决方案