当用户设置为非活动时,不要在 Identity Server 4 中发出令牌
Don't issue a token in Identity Server 4 when a user is set to inactive
我们最近通过 Identity.AspNetUsers
table 中的“活动”布尔字段实现了在我们的应用程序中禁用用户的功能。登录到后台系统(一个 Angular 应用程序)很容易通过隐式流程处理——只需在调用 PasswordSignInAsync
.
之前检查该字段
我们无法找到一种方法来阻止使用调用内置 ID Server 4 端点的姊妹应用程序(用 Flutter 编写)为任何移动设备颁发令牌 /connect/token
。同样,我们无法阻止应用程序请求并接收有效的刷新令牌。我们不能硬删除用户,因为我们有硬链接到数据库中的其他 table 以用于审计目的。
如有任何帮助,我们将不胜感激。
我们正在使用 DotNET Core 3,1。
编辑:我们正在使用密码授予类型。
当客户端使用刷新令牌请求新的访问令牌时,就会涉及到RefreshTokenService。通过自定义刷新令牌行为,您可以查找用户是否被禁用,然后拒绝颁发新的访问令牌。有关如何执行此操作的更多详细信息,请参阅此 page。
或者,如果用户被禁用,您可以在实现 IPersistedGrantStore 的 class 中添加一些代码来查找,然后 return
return Task.FromResult<PersistedGrant>(null!);
被屏蔽时。
当使用内置 /connect/token
端点的密码授予时,您实现接口 ICustomTokenRequestValidator
并将其作为 Transient 添加到服务集合中。这有一种方法,ValidateAsync
,如果您的请求引用的用户有效,您只需 return
并且管道将照常继续。如果您的用户无效,您将 CustomTokenRequestValidationContext
上的 Result.IsError
属性 设置为 true,并在 return 之前向 Result.Error
提供一个字符串,这样令牌就可以了未发行。
注入 UserManager<T>
和 IHttpContextAccessor
以便您可以从该方法访问用户名和用户存储。
这是一个实现:
public class CustomTokenRequestValidator : ICustomTokenRequestValidator
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly IHttpContextAccessor _httpContextAccessor;
private const string errorMessage = "invalid_username_or_password";
public CustomTokenRequestValidator(
UserManager<ApplicationUser> userManager
, IHttpContextAccessor httpContextAccessor)
{
_userManager = userManager;
_httpContextAccessor = httpContextAccessor;
}
public async Task ValidateAsync(CustomTokenRequestValidationContext context)
{
_httpContextAccessor.HttpContext.Request.Form.TryGetValue("username", out var userOut);
var u = userOut.ToString();
if(u != null)
{
var user = await _userManager.FindByEmailAsync(u);
if(user == null || !user.Active)
{
context.Result.IsError = true;
context.Result.Error = errorMessage;
}
} else
{
context.Result.IsError = true;
context.Result.Error = errorMessage;
}
return;
}
}
我们最近通过 Identity.AspNetUsers
table 中的“活动”布尔字段实现了在我们的应用程序中禁用用户的功能。登录到后台系统(一个 Angular 应用程序)很容易通过隐式流程处理——只需在调用 PasswordSignInAsync
.
我们无法找到一种方法来阻止使用调用内置 ID Server 4 端点的姊妹应用程序(用 Flutter 编写)为任何移动设备颁发令牌 /connect/token
。同样,我们无法阻止应用程序请求并接收有效的刷新令牌。我们不能硬删除用户,因为我们有硬链接到数据库中的其他 table 以用于审计目的。
如有任何帮助,我们将不胜感激。
我们正在使用 DotNET Core 3,1。
编辑:我们正在使用密码授予类型。
当客户端使用刷新令牌请求新的访问令牌时,就会涉及到RefreshTokenService。通过自定义刷新令牌行为,您可以查找用户是否被禁用,然后拒绝颁发新的访问令牌。有关如何执行此操作的更多详细信息,请参阅此 page。
或者,如果用户被禁用,您可以在实现 IPersistedGrantStore 的 class 中添加一些代码来查找,然后 return
return Task.FromResult<PersistedGrant>(null!);
被屏蔽时。
当使用内置 /connect/token
端点的密码授予时,您实现接口 ICustomTokenRequestValidator
并将其作为 Transient 添加到服务集合中。这有一种方法,ValidateAsync
,如果您的请求引用的用户有效,您只需 return
并且管道将照常继续。如果您的用户无效,您将 CustomTokenRequestValidationContext
上的 Result.IsError
属性 设置为 true,并在 return 之前向 Result.Error
提供一个字符串,这样令牌就可以了未发行。
注入 UserManager<T>
和 IHttpContextAccessor
以便您可以从该方法访问用户名和用户存储。
这是一个实现:
public class CustomTokenRequestValidator : ICustomTokenRequestValidator
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly IHttpContextAccessor _httpContextAccessor;
private const string errorMessage = "invalid_username_or_password";
public CustomTokenRequestValidator(
UserManager<ApplicationUser> userManager
, IHttpContextAccessor httpContextAccessor)
{
_userManager = userManager;
_httpContextAccessor = httpContextAccessor;
}
public async Task ValidateAsync(CustomTokenRequestValidationContext context)
{
_httpContextAccessor.HttpContext.Request.Form.TryGetValue("username", out var userOut);
var u = userOut.ToString();
if(u != null)
{
var user = await _userManager.FindByEmailAsync(u);
if(user == null || !user.Active)
{
context.Result.IsError = true;
context.Result.Error = errorMessage;
}
} else
{
context.Result.IsError = true;
context.Result.Error = errorMessage;
}
return;
}
}