.net core Don';当用户设置为非活动时,不要在Identity Server 4中发出令牌

.net core Don';当用户设置为非活动时,不要在Identity Server 4中发出令牌,.net-core,identityserver4,openid-connect,.net Core,Identityserver4,Openid Connect,最近,我们在Identity.AspNetUsers表中使用“Active”布尔字段实现了在应用程序中禁用用户的功能。登录到后台系统(一个角度应用程序)很容易通过隐式流处理——只需在调用PasswordSignInAsync之前检查字段即可 我们无法找到一种方法来阻止使用姊妹应用程序(用flatter编写)为任何移动设备颁发令牌,该应用程序调用内置的ID Server 4端点/connect/token。同样,我们不能阻止应用程序请求并接收有效的刷新令牌。我们无法硬删除该用户,因为出于审计目的,

最近,我们在
Identity.AspNetUsers
表中使用“Active”布尔字段实现了在应用程序中禁用用户的功能。登录到后台系统(一个角度应用程序)很容易通过隐式流处理——只需在调用
PasswordSignInAsync
之前检查字段即可

我们无法找到一种方法来阻止使用姊妹应用程序(用flatter编写)为任何移动设备颁发令牌,该应用程序调用内置的ID Server 4端点
/connect/token
。同样,我们不能阻止应用程序请求并接收有效的刷新令牌。我们无法硬删除该用户,因为出于审计目的,我们有到数据库中其他表的硬链接

任何帮助都将不胜感激

我们使用的是DotNET Core 3,1


编辑:我们使用的是密码授权类型。

当客户端使用刷新令牌请求新的访问令牌时,就会涉及到刷新令牌服务。通过自定义刷新令牌行为,您可以查找用户是否已禁用,然后拒绝发出新的访问令牌。有关如何执行此操作的更多详细信息,请参见此

或者,如果用户被禁用,则可以在实现IPersistedGrantStore的类中为查找添加一些代码,然后返回

return Task.FromResult<PersistedGrant>(null!);
返回任务.FromResult(null!);

被阻止时。

当客户端使用刷新令牌请求新的访问令牌时,则涉及刷新令牌服务。通过自定义刷新令牌行为,您可以查找用户是否已禁用,然后拒绝发出新的访问令牌。有关如何执行此操作的更多详细信息,请参见此

或者,如果用户被禁用,则可以在实现IPersistedGrantStore的类中为查找添加一些代码,然后返回

return Task.FromResult<PersistedGrant>(null!);
返回任务.FromResult(null!);

当被阻止时。

当对内置的
/connect/token
端点使用密码授权时,您实现接口
ICustomTokenRequestValidator
,并将其作为瞬态添加到服务集合中。这有一个方法,
ValidateAsync
,如果您的请求引用的用户有效,您只需
返回
,管道将正常运行。如果用户无效,请将
CustomTokenRequestValidationContext
上的
Result.IsError
属性设置为true,并在返回之前向
Result.Error提供一个字符串,这样就不会颁发令牌

注入
UserManager
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;
        }
    }
公共类CustomTokenRequestValidator:ICustomTokenRequestValidator
{
私有只读用户管理器_UserManager;
专用只读IHttpContextAccessor\u httpContextAccessor;
private const string erromessage=“无效的用户名或密码”;
公共CustomTokenRequestValidator(
用户管理器用户管理器
,IHttpContextAccessor httpContextAccessor)
{
_userManager=userManager;
_httpContextAccessor=httpContextAccessor;
}
公共异步任务ValidateAsync(CustomTokenRequestValidationContext上下文)
{
_httpContextAccessor.HttpContext.Request.Form.TryGetValue(“用户名”,out var userOut);
var u=userOut.ToString();
如果(u!=null)
{
var user=await\u userManager.findbyemailsync(u);
if(user==null | |!user.Active)
{
context.Result.IsError=true;
context.Result.Error=错误消息;
}
}否则
{
context.Result.IsError=true;
context.Result.Error=错误消息;
}
返回;
}
}

当对内置的
/connect/token
端点使用密码授权时,您实现接口
ICustomTokenRequestValidator
,并将其作为瞬态添加到服务集合中。这有一个方法,
ValidateAsync
,如果您的请求引用的用户有效,您只需
返回
,管道将正常运行。如果用户无效,请将
CustomTokenRequestValidationContext
上的
Result.IsError
属性设置为true,并在返回之前向
Result.Error提供一个字符串,这样就不会颁发令牌

注入
UserManager
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;
        }
    }
公共类CustomTokenRequestValidator:ICustomTokenRequestValidator
{
私有只读用户管理器_UserManager;
专用只读IHttpContextAccessor\u httpContextAccessor;
private const string erromessage=“无效的用户名或密码”;
公共CustomTokenRequestValidator(
用户管理器用户管理器
,IHttpContextAccessor httpContextAccessor)
{
_userManager=userManager;
_httpContextAccessor=httpContextAccessor;
}
公共异步任务ValidateAsync(CustomTokenRequestValidationContext上下文)
{
_httpContextAccessor.HttpContext.Request.Form.TryGetValue(“用户名”,out var userOut);
var u=userOut.ToString();
如果(u!=null)
{
var user=await\u userManager.findbyemailsync(u);
if(user==null | |!user.Active)
{
context.Result.IsError=true;
context.Result.Error=错误消息;
}
}否则
{
context.Result.IsError=true;
有限公司