asp.net-web-api - 关于存储令牌值的 OAuth 2.0 基于令牌的身份验证问题
问题描述
我已经在我们的 WebAPI 应用程序中实现了基于 OAuth 令牌的身份验证,并针对数据库验证了用户名和密码。但我们不会将访问令牌和刷新令牌同步到任何类型的数据库。这是代码,但是,我有一个问题,令牌值的存储位置。
下面的代码生成令牌
/// <summary>
/// Grant resource owner credentials overload method.
/// </summary>
/// <param name="context">Context parameter</param>
/// <returns>Returns when task is completed</returns>
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
// Initialization.
var usernameVal = context.UserName;
var passwordVal = context.Password;
var user = _securityLogic.AuthenticateApiUser(usernameVal, passwordVal);
// Verification.
if (!user)
{
// Settings.
context.SetError("invalid_grant", "The user name or password is incorrect.");
// Return info.
return;
}
// Initialization.
var claims = new List<Claim>
{
//var userInfo = user.FirstOrDefault();
// Setting
new Claim(ClaimTypes.Name, usernameVal)
};
// Setting Claim Identities for OAUTH 2 protocol.
ClaimsIdentity oAuthClaimIdentity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
ClaimsIdentity cookiesClaimIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType);
// Setting user authentication.
AuthenticationProperties properties = CreateProperties(usernameVal);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthClaimIdentity, properties);
// Grant access to authorize user.
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesClaimIdentity);
}
#endregion
#region Token endpoint override method.
/// <summary>
/// Token endpoint override method
/// </summary>
/// <param name="context">Context parameter</param>
/// <returns>Returns when task is completed</returns>
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
{
// Adding.
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
// Return info.
return Task.FromResult<object>(null);
}
#endregion
这是用于生成刷新令牌的代码
#region GrantRefreshToken
private static readonly ConcurrentDictionary<string, AuthenticationTicket> RefreshTokens =
new ConcurrentDictionary<string, AuthenticationTicket>();
/// <summary>
/// Grants Refresh Token
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
{
// Change authentication ticket for refresh token requests
var newIdentity = new ClaimsIdentity(context.Ticket.Identity);
// newIdentity.AddClaim(new Claim("newClaim", "newValue"));
var newTicket = new AuthenticationTicket(newIdentity, context.Ticket.Properties);
context.Validated(newTicket);
return Task.FromResult<object>(null);
}
public async Task CreateAsync(AuthenticationTokenCreateContext context)
{
var guid = Guid.NewGuid().ToString();
// Copy claims from the previous token
var refreshTokenProperties = new AuthenticationProperties(context.Ticket.Properties.Dictionary)
{
IssuedUtc = context.Ticket.Properties.IssuedUtc,
ExpiresUtc = DateTime.UtcNow.AddMinutes(30)
};
var refreshTokenTicket = await Task.Run(() =>
new AuthenticationTicket(context.Ticket.Identity, refreshTokenProperties));
RefreshTokens.TryAdd(guid, refreshTokenTicket);
// Consider storing only the hash of the handle
context.SetToken(guid);
}
#endregion
所以,我的问题是 .NET/Owin/IdentityServer3 将它们写入一些内存数据库?如果是这样,是否可以访问它们以进行查看和删除等操作?如果重新启动应用服务器会发生什么,是否所有令牌都被清除了?还是他们坚持不懈?
您是否建议将其存储在数据库中并从数据库中检索?任何帮助表示赞赏,顺便说一句,这段代码工作得很好。
解决方案
从文档中:
如果没有特别配置,我们将始终为授权代码、同意、参考和刷新令牌提供内存版本存储。
请注意,他们谈论的是参考令牌和刷新令牌。不存储 JWT 访问令牌和身份令牌。
为了在 IdentityServer3 (以及IdentityServer4 )中使用刷新令牌,它必须匹配存储的令牌。
这样做的主要好处是您可以控制令牌。您可以撤销它(从商店中删除它),并定义如何使用它:一次性或重复使用。
我对IdentityServer3不熟悉,但是你可以看一下github并搜索实现RevocationEndpoint的代码,即从商店中删除刷新令牌的地方。这可能会为如何访问和使用商店提供线索。
使用内存存储,令牌在 IdentityServer 重新启动时丢失。因此,将它们持久存储在数据库等持久存储中,对于生产服务器来说是一件好事。对于 IdentityServer4,您可以实现一个操作存储。
请注意,无论重新启动服务器,JWT 令牌都保持有效,除非私钥也没有持久化。在这种情况下,IdentityServer 无法验证令牌并且别无选择,只能将 JWT 令牌视为无效。
因此,对于生产环境,您应该保留密钥和数据,并且使用数据库很好。正如您在 IdentityServer4 中看到的那样,对此有支持。
说到 IdentityServer4,既然对 IdentityServer3 的(免费)支持已经结束,我建议您切换到 IdentityServer4,如果您可以这样做的话。由于两个版本都实现了 oidc/auth2,您应该能够继续使用升级后的 IdentityServer 客户端。在 stackoverflow 上有一些问题可以帮助你。并查看 IdentityServer4 文档,它提供了非常丰富的信息。
推荐阅读
- python - 在我的 Django 中为博客文章创建一个赞按钮?
- reactjs - 如何在反应原生中使用反应导航添加类似顶部选项卡的whatsapp
- c - 增量编码器 - 轮询或中断?
- asp.net-core - 学习.Net core 5 项目
- linux - Fedora 的 Gcc-multilib
- javascript - discord.js 的参数中的空格
- python - 具有重复值的 Pandas 数据透视表
- java - Java 模块化。错误:找到两个版本的模块 jakarta.activation(jakarta.activation-api-1.2.2.jar 和 jakarta.activation-1.2.2.jar)
- php - Woocommerce:如果当前产品在购物车中,则将 Body 类添加到产品页面
- xml - Scala - 从文件加载 XML 并覆盖文本值