2014-11-06 5 views
18

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

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

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

+0

Не является частью точки с OAuth, что она независима от изменений пароля? Почему бы просто не удалить маркер с сервера аутентификации, когда они меняют пароль, а затем, если они попытаются использовать его на других устройствах, он не будет работать. – DaImTo

+0

«Почему бы просто не удалить токен с сервера аутентификации»: возможно ли это с помощью ASP.NET Identity? Я думал, что токены являются самодостаточными, поэтому их можно использовать на любом экземпляре веб-сервера, поэтому у нас нет сервера аутентификации. –

+0

Если это правда, тогда мне кажется, что мне нужно обновить «ASP.NET Identity». Сожалею. – DaImTo

ответ

12

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

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

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

+1

Это было просто реализовать и работать правильно. Благодаря! –

+2

Рад, что это было полезно.Если вы хотите, чтобы вы не делили часть кода, который вы создали для его реализации, я уверен, что он будет полезен для других :) –

+2

Я разместил некоторые детали кода. –

12

Я основывал свой подход на предложении Тайсера. Суть решения заключается в следующем. Каждый раз, когда пользователь меняет свой пароль (и когда регистрируется), создается новый GUID и сохраняется в базе данных в таблице User. Я называю этот идентификатор штампом и сохраняю его в собственности под названием 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); 
    } 
} 

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

+2

Хорошее решение: нет ли официального пути, который предлагает OAuth, мы обрабатываем такие случаи? Я имею в виду, что это серьезная дыра во всей схеме аутентификации, если все устройства могут получить доступ, как только пароль был изменен. – Zapnologica

+1

Да, я думаю, здесь проблема заключается в том, что сам OAuth ничего не знает о том, откуда взялись эти личности, это ответственность поставщика удостоверений. Например, здесь ASP.NET Identity и встроенные средства обработчика OAuth являются отдельными и не знают друг о друге, поэтому мы должны вручную разрешить обработчику токенов знать, что пароль был изменен. –

+0

Мое предложенное решение ниже работает в соответствии с вашим опытом? http://stackoverflow.com/questions/29534111/oauth-access-and-refresh-token-control-on-password-change – Zapnologica

Смежные вопросы