Подтвердить что ты не робот

Как аннулировать токен OAuth при изменении пароля?

Мы используем идентификатор ASP.NET в проекте Web Api с SimpleAuthorizationServerProvider, мы используем OAuth-tokens для авторизации каждого запроса, исходящего от клиента. (У токенов есть и срок действия, мы не используем токены обновления.)

Когда пользователи меняют свой пароль, я хотел бы аннулировать маркеры, которые они могут иметь, возможно, на других устройствах. Есть ли способ явно сделать это? Я экспериментировал и видел, что существующие токены работают без каких-либо проблем после смены пароля, которые следует предотвратить.

Я подумал о том, чтобы положить хэш хэша или часть хэша в токен OAuth в качестве претензии, и проверить это в методе OnAuthorization нашего производного фильтра AuthorizeAttribute.
Будет ли это правильным способом решения проблемы?

4b9b3361

Ответ 1

Я не рекомендую помещать хэш пароля в качестве претензии, и я считаю, что нет прямого способа сделать недействительным токен при изменении пароля.

Но если вы работаете с БД с каждым запросом, отправляющим из клиентского приложения в защищенную конечную точку API, то вам нужно хранить идентификатор токена (возможно, Guid) для каждого токена, предоставленного владельцу ресурса, который запросил его. Затем вы назначаете идентификатор токена в качестве пользовательской заявки для этого токена, после чего вам нужно проверить эту таблицу с каждым запросом, ища идентификатор маркера и имя пользователя для владельца ресурса.

После изменения пароля вы удаляете эту запись идентификатора маркера для этого владельца ресурса (пользователя), а в следующий раз, когда токен, отправленный от клиента, будет отклонен, поскольку запись для этого идентификатора маркера и владельца ресурса была удалена.

Ответ 2

Я основывал свой подход на предложении Тайсера. Суть решения заключается в следующем. Каждый раз, когда пользователь меняет свой пароль (и когда регистрируется), создается новый GUID и сохраняется в базе данных в таблице User. Я называю этот GUID штампом пароля и сохраняю его в свойстве LatestPasswordStamp.

Этот штамп должен быть отправлен клиенту как часть токена в качестве требования. Это может быть достигнуто с помощью следующего кода в методе GrantResourceOwnerCredentials реализации OAuthAuthorizationServerProvider.

identity.AddClaim( new Claim( "PasswordTokenClaim", user.LatestPasswordStamp.ToString() ) );

Эта марка будет отправляться от клиента на сервер в каждом запросе и проверяется, что штамп не был изменен в базе данных. Если это так, это означает, что пользователь изменил свой пароль, возможно, с другого устройства. Проверка выполняется в нашем настраиваемом фильтре авторизации следующим образом.

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 );
    }
}

Таким образом, клиент получает ошибку авторизации, если он пытается авторизовать себя с токеном, который был выпущен до того, как пароль был изменен.