密码更改后如何使OAuth令牌无效?

Mar*_*cze 21 oauth asp.net-web-api asp.net-identity

我们在Web Api项目中使用ASP.NET Identity SimpleAuthorizationServerProvider,我们使用OAuth-tokens来授权来自客户端的每个请求.(标记有时间和到期时间,我们不使用刷新令牌.)

当用户更改密码时,我想使他们可能拥有的令牌无效,可能在其他设备上.有没有办法明确这样做?我进行了实验,发现密码更改后现有令牌的运行没有任何问题,应该加以防范.

我考虑过将密码哈希或OAuth令牌中的部分哈希作为声明,并在OnAuthorization派生的AuthorizeAttribute过滤器的方法中验证.
这是解决问题的正确方法吗?

Mar*_*cze 13

我的方法是基于Taiseer的建议.解决方案的要点如下.每次用户更改其密码(以及注册时)时,都会生成一个新的GUID并将其保存在User表的数据库中.我将此GUID称为密码标记,并将其存储在名为的属性中LatestPasswordStamp.

此戳记必须作为声明的一部分发送给客户端作为声明的一部分.这可以通过-implementation GrantResourceOwnerCredentials方法中的以下代码来实现OAuthAuthorizationServerProvider.

identity.AddClaim( new Claim( "PasswordTokenClaim", user.LatestPasswordStamp.ToString() ) );
Run Code Online (Sandbox Code Playgroud)

此戳记将在每个请求中从客户端发送到服务器,并验证数据库中的戳记未被更改.如果是,则表示用户可能从其他设备更改了密码.验证是在我们的自定义授权过滤器中完成的.

public class AuthorizeAndCheckStampAttribute : AuthorizeAttribute
{
    public override void OnAuthorization( HttpActionContext actionContext )
    {
        var claimsIdentity = actionContext.RequestContext.Principal.Identity as ClaimsIdentity;
        if( claimsIdentity == null )
        {
            this.HandleUnauthorizedRequest( actionContext );
        }

        // Check if the password has been changed. If it was, this token should be not accepted any more.
        // We generate a GUID stamp upon registration and every password change, and put it in every token issued.
        var passwordTokenClaim = claimsIdentity.Claims.FirstOrDefault( c => c.Type == "PasswordTokenClaim" );

        if( passwordTokenClaim == null )
        {
            // There was no stamp in the token.
            this.HandleUnauthorizedRequest( actionContext );
        }
        else
        {
            MyContext ctx = (MyContext)System.Web.Mvc.DependencyResolver.Current.GetService( typeof( MyContext ) );

            var userName = claimsIdentity.Claims.First( c => c.Type == ClaimTypes.Name ).Value;

            if( ctx.Users.First( u => u.UserName == userName ).LatestPasswordStamp.ToString() != passwordTokenClaim.Value )
            {
                // The stamp has been changed in the DB.
                this.HandleUnauthorizedRequest( actionContext );
            }
        }

        base.OnAuthorization( actionContext );
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,如果客户端尝试使用在更改密码之前发出的令牌授权自身,则会收到授权错误.

  • 很好的解决方案,OAuth建议我们处理此类案件是否没有官方方式?我的意思是,如果密码更改后所有设备仍然可以访问,那么它似乎是整个身份验证方案中的一个严重漏洞. (2认同)

Tai*_*deh 12

我不建议将密码的哈希值作为声明,我相信在密码更改时没有直接的方法来使令牌无效.

但是,如果您通过从客户端应用程序发送到受保护的API端点的每个请求命中数据库,那么您需要为授予资源所有者请求的每个令牌存储令牌标识符(可能是Guid).然后,您将令牌标识符指定为此令牌的自定义声明,之后您需要通过查找令牌标识符和资源所有者的用户名来检查每个请求的此表.

更改密码后,删除此资源所有者(用户)的此令牌标识符记录,下次从客户端发送令牌时,它将被拒绝,因为此令牌标识符和资源所有者的记录已被删除.

  • 很高兴它很有帮助.如果你想为什么你不共享你为实现它而创建的部分代码,我相信它对其他人有用:) (2认同)