#asp.net #oauth #owin #access-token #race-condition
#asp.net #oauth #owin #токен доступа #условие гонки
Вопрос:
Я предоставил конвейеру owin свой собственный CookieAuthenticationProvider с
public async override Task ValidateIdentity(CookieValidateIdentityContext context)
В этом методе я проверяю сторонний токен в заявках идентификатора пользователя, чтобы узнать, истек ли срок его действия или близок к истечению. Если это так, я использую его токен обновления для получения нового токена доступа от третьей стороны, создаю новый идентификатор с новыми токенами доступа и обновления, затем выполняю вход и заменяю текущий идентификатор. Таким образом, у пользователя всегда есть действительный токен доступа к стороннему сайту.
Это работает довольно безупречно, за исключением того, что у нас много запросов ajax, а также поступают некоторые запросы signalr в режиме реального времени. Таким образом, очень часто 2 запроса от пользователя будут обрабатываться в разных потоках A amp; B. Поток A сначала попадает в атрибут [Authorize], который запускает Validate-identity. Он видит, что токен будет или истек, и требует обновления. Тем временем поток B заканчивает тем, что делает то же самое. Поток A завершается первым и теперь имеет новый токен доступа и токен обновления, поток B не обновляется, потому что он вызвал обновление с использованием исходного токена обновления, который третья сторона теперь считает недействительным и отклоняет любой новый токен доступа, поэтому запрос пользователей становится несанкционированным. Поток A завершается, и все выглядит хорошо. Поток B завершается ошибкой, что бы он ни собирался делать в первую очередь.
Мой вопрос в том, подходящее ли это место для этого? Есть ли лучший способ? Как я могу избежать этого состояния гонки?
Ответ №1:
Если вы хотите синхронизировать два запроса, вам нужна центральная служба выкупа токенов. Вы можете даже не хранить токены в user info / cookie, а хранить их непосредственно в сервисе, и пусть тот, кому нужны токены, запрашивает их у сервиса. По запросу вы можете проверить наличие обновления и убедиться, что одновременно выполняется только одно обновление.
Комментарии:
1. Я собираюсь установить это в качестве ответа, потому что лучшая практика действительно вращается вокруг такого решения, если у вас должно быть 2 асинхронных токена с разным временем обновления. В итоге нам пришлось добавить фильтр MVC, который делает это, что является хакерским, но работает.
2. @dasamigo Не могли бы вы подробнее рассказать о том, как вы обычно реализовали этот фильтр? Некоторое время назад мы столкнулись с той же проблемой (хотя и для приложения Rails). Похоже, что MVC-фильтр работает без совместного использования состояния между несколькими серверами приложений, но, возможно, я просто неправильно понимаю, что вы сделали.