Oauth2 Implicit Flow с токенами доступа для обновления на одной странице приложения
Я использую Thinktecture AuthorizationServer (AS), и он отлично работает.
Я хотел бы написать собственное одностраничное приложение на javascript, которое может напрямую вызывать WebAPI, однако неявный поток не предоставляет токен обновления.
Если будет выполнен вызов AJAX, если срок действия токена истек, API отправит перенаправление на страницу входа в систему, поскольку данные используют динамические всплывающие окна, и это прервет пользователя.
Как Facebook или Stackru делают это и все еще позволяют JavaScript, запущенному на странице, вызывать API?
Предложенное решение
Имеет ли смысл приведенный ниже сценарий (при условии, что это можно сделать с помощью фреймов):
Мой SPA направляет меня в AS, и я получаю токен от Implicit Flow. В AS я нажимаю Read data
область и нажмите Remember decision
, затем Allow
кнопка.
Так как я нажал Remember decision
Кнопка, всякий раз, когда я нажимаю AS для токена, новый токен передается обратно автоматически, и мне не нужно входить в систему (я вижу файл cookie FedAuth, который запоминает мое решение и верит, что это позволяет просто работать).
С моим SPA (ненадежным приложением) у меня нет токена обновления только токена доступа. Итак, вместо этого я:
- Убедитесь, что пользователь вошел в систему и нажал кнопку запомнить решение (иначе iframe не будет работать)
- Позвоните в WebAPI, если ответ 401 попытается получить новый токен, выполнив следующие действия...
- У меня есть скрытый iframe на странице, на котором я задам URL, чтобы получить новый токен доступа с Сервера авторизации.
- Получите новый токен из хеш-фрагмента iframe, затем сохраните его в SPA и используйте для всех будущих запросов WebAPI.
Я думаю, что у меня все еще были бы проблемы, если бы файл cookie FedAuth был украден.
Любой стандартный или рекомендуемый способ для вышеупомянутого сценария?
4 ответа
В Google o-Auth токен доступа будет действителен только в течение 1 часа, поэтому вам нужно программно обновлять свой токен доступа через каждый час, просто вы можете создать веб-API для этого, вам нужно иметь токен обновления и также, что токен обновления не истечет, используя код C#, я сделал это.
if (dateTimeDiff > 55)
{
var request = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/oauth2/v3/token");
var postData = "refresh_token=your refresh token";
postData += "&client_id=your client id";
postData += "&client_secret=your client secrent";
postData += "&grant_type=refresh_token";
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
request.UseDefaultCredentials = true;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
вам нужно где-то сохранить последнее обновленное время даты токена доступа (скажем, в базе данных), чтобы каждый раз, когда вам нужно было сделать запрос, чтобы вы могли вычесть его из текущего времени даты, если оно превышает 60 минут, вы нужно получить webapi, чтобы получить новый токен.
Я понимаю, что ваша проблема заключается в том, что по истечении срока действия маркера доступа у пользователя возникнет сбой при перенаправлении на страницу входа на сервере авторизации. Но я не думаю, что вы можете и должны обойти это, по крайней мере, при использовании неявного гранта.
Как я уверен, вы уже знаете, что неявное предоставление должно использоваться потребителями, которые НЕ могут хранить свои учетные данные в секрете. Из-за этого токен доступа, который выдается сервером авторизации, должен иметь ограниченный ttl. Например, Google аннулирует свой токен доступа за 3600 секунд. Конечно, вы можете увеличить ttl, но он никогда не должен становиться долгоживущим токеном.
Также следует отметить, что, по моему мнению, прерывание пользователя очень минимально, то есть, если оно реализовано правильно, пользователь должен будет пройти аутентификацию только один раз на сервере авторизации. После этого (например, при первой авторизации доступа приложения к любым ресурсам, которые пользователь контролирует) будет установлен сеанс (на основе файлов cookie или маркеров) и при получении токена доступа потребителя (веб-приложение, использующее неявное предоставление). По истечении срока действия пользователь будет уведомлен о том, что срок действия токена истек, и потребуется повторная аутентификация на сервере авторизации. Но поскольку сеанс уже был установлен, пользователь будет немедленно перенаправлен обратно в веб-приложение.
Однако, если это не то, что вам нужно, вы, по моему мнению, должны рассмотреть возможность использования кода авторизации вместо того, чтобы делать сложные вещи с iframes. В этом случае вам понадобится веб-приложение на стороне сервера, потому что тогда вы сможете сохранить свои учетные данные в секрете и использовать токены обновления.
Похоже, вам нужно ставить запросы в очередь в случае истечения срока действия токена доступа. Это более или менее так, как это делают Facebook и Google. Простой способ использования Angular - добавить перехватчик HTTP и проверить ответы HTTP401. Если один возвращается, вы повторно аутентифицируете и ставите в очередь любые запросы, поступающие после, пока запрос на аутентификацию не будет выполнен (то есть обещание). Как только это будет сделано, вы можете обработать ожидающую очередь с вновь возвращенным токеном доступа из вашего запроса аутентификации, используя свой токен обновления.
Удачного кодирования.
Не уверен, что понимаю ваш вопрос, но
Я хотел бы написать собственное одностраничное приложение на javascript, которое может напрямую вызывать WebAPI, однако неявный поток не предоставляет токен обновления.
Обобщать факты,
токен обновления иногда используется как часть A: Авторизация
https://tools.ietf.org/html/rfc6749
и, как вы сказали в неявном потоке, вы не получите токен обновления, а только в части авторизации.
https://tools.ietf.org/html/rfc6749
так что вы можете получить токен обновления при выдаче токена доступа (токены обновления всегда необязательны)
https://tools.ietf.org/html/rfc6749
С моим SPA (ненадежным приложением) у меня нет токена обновления только токена доступа. Итак, вместо этого я:
1) Убедитесь, что пользователь вошел в систему и нажал кнопку запомнить решение (в противном случае iframe не будет работать)
2) Вызовите WebAPI, если ответ 401 попытается получить новый токен, выполнив следующие действия...
3) Иметь скрытый iframe на странице, на котором я буду устанавливать URL, чтобы получить новый токен доступа с Сервера авторизации.
4) Получить новый токен из хеш-фрагмента iframe, затем сохранить его в SPA и использовать для всех будущих запросов WebAPI.
1) SPA (вы) понятия не имеете, выбрал ли пользователь запомнить решение. Его в направлении AS и должен быть полный черный ящик. Пропустить этот шаг.
2) Вы можете попытаться использовать токен доступа и ждать результата всегда.
3) Если токен доступа истек и у вас нет обновленного токена, вы все равно можете создать скрытый iframe и попытаться получить новый токен доступа.
4) Давайте предположим, что ваша AS предоставляет возможность запомнить решение и не будет его менять в будущем, затем: ваш iframe получит новый токен доступа без взаимодействия с пользователем, затем вы получите результат обратно в некое неизвестное время. Результат может быть проверен setInterval
для чтения определенных файлов cookie или iframe postmessage
, Если вы не вернули данные в срок, то произошел один из следующих сценариев:
- задержка, AS медленный, соединение медленное или слишком мало времени
- пользователь не выбрал запомнить решение
В этом случае:
5) показать iframe с логином
Я считаю, что приведенный выше сценарий является хорошей практикой, если AS не предоставляет токены обновления, но я также предполагаю, что каждая подобная AS также не предоставляет опцию запоминания.
Stackru <---> Google сценарий (я могу только догадываться)
1) Логин пользователя, запрос авторизации произошел
2) Пользователь входит в систему, ТАК получает токен доступа
3) ТАК пытается использовать токен доступа
4) ТАК возвращает результат + обновить токен
5) ТАК сохраняет токен обновления
6) ТАК имеет постоянный доступ к аккаунту пользователей Google