Корень проблемы заключается в использовании iframe
и типа неявного предоставления.
Я думаю, что причиной использования iframe является доступ к cookie-файлам через домены.Теперь, самый простой способ избежать использования iframe
- это установить домен cookie как Domain=example.com
, а пользовательский интерфейс и сервер авторизации - на example.com
.Если по какой-либо причине вы не можете этого сделать, вам необходимо придерживаться следующего подхода:
Рекомендуемая опция
Неявный тип предоставления не защищен.Хотя этот вопрос не о плюсах и минусах типов грантов, для того, чтобы установить фон для опции, которую я собираюсь объяснить, позвольте мне кратко перечислить причины, по которым я говорю, что неявный поток не защищен:
- Отсутствует этап аутентификации клиента, в котором указывается секрет клиента и код авторизации.Таким образом, снижается уровень безопасности
- Токен доступа отправляется обратно в виде фрагмента URL (чтобы токен не отправлялся на сервер), который будет оставаться в истории браузера
- Если XSS-атака произойдетвредоносный сценарий может очень хорошо отправить токен на удаленный сервер, контролирующий злоумышленника
Поэтому рекомендуется использовать тип предоставления кода авторизации.Одна из причин, по которой не используется код авторизации в SPA (одностраничное приложение), заключается в том, что он требует сохранения секрета клиента в браузере, и мы знаем, что браузер не может хранить секреты.Этот риск можно очень легко снизить, если иметь на стороне сервера прокси-компонент (может быть встроен в сервер ресурсов), который будет хранить секрет клиента и действовать как прокси между SPA и сервером авторизации.
Здесь(в типе предоставления кода авторизации) процесс выглядит следующим образом:
- пользователь нажимает кнопку входа в систему на целевой странице SPA
- пользователь перенаправляется на сервер авторизациистр.Идентификатор клиента указывается в параметре запроса URL
. Пользователь вводит свои учетные данные и нажимает кнопку входа в систему.Имя пользователя и пароль будут отправлены на сервер авторизации с использованием HTTP POST.Учетные данные следует отправлять в теле или заголовке запроса, а НЕ в URL (так как URL-адреса регистрируются в истории браузера и на сервере приложений).Кроме того, должны быть установлены правильные заголовки кэширования HTTP, чтобы учетные данные не кэшировались: Cache-Control: no-cache, no-store, Pragma: no-cache, Expires: 0
Сервер авторизации аутентифицирует пользователя по пользовательской базе данных (скажем, серверу LDAP), где имя пользователя и хеш пароля пользователя (алгоритмы хеширования, такие как Argon2, PBKDF2, Bcrypt или Scrypt) хранятся со случайной солью
- При успешной аутентификации сервер авторизации извлекает из своей базы данных URL-адрес перенаправления по указанному идентификатору клиента в параметре запроса URL-адреса.URL-адрес перенаправления - это URL-адрес сервера ресурсов
- . Затем пользователь будет перенаправлен на конечную точку сервера ресурсов с кодом авторизации в параметре запроса URL-адреса
- . Затем сервер ресурсов выполнит запрос HTTP POST.к серверу авторизации для токена доступа.Код авторизации, идентификатор клиента, секрет клиента должны быть указаны в теле запроса.(Следует использовать соответствующие заголовки кэширования, как указано выше)
- Сервер авторизации возвращает токен доступа и токен обновления в теле или заголовке ответа (с соответствующим заголовком кэширования, как упомянуто выше)
- сервер ресурсов теперь перенаправляет пользователя (код ответа HTTP 302) на URL-адрес SPA, установив соответствующие файлы cookie с атрибутом домена как
Domain=example.com
(при условии, что оба сервера ресурсов и пользовательский интерфейс находятся в поддоменах example.com
).Домен сервера авторизации не имеет значения, поскольку он не устанавливает файлы cookie.
Таким же образом, запрос на обновление токена доступа может быть отправлен на прокси-компонент, который будет считывать токены обновления и доступа из куки-файла и вызывать API-интерфейс авторизации с извлеченными таким образом токенами, идентификатором клиента иСекрет клиента.