Вопрос или проблема
https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1 указывает:
4.1.1. Запрос авторизации”
“state”
РЕКОМЕНДУЕТСЯ. Непрозрачное значение, используемое клиентом для поддержания
состояния между запросом и обратным вызовом. Сервер авторизации
включает это значение при перенаправлении пользовательского агента обратно
к клиенту. Параметр ДОЛЖЕН использоваться для предотвращения
межсайтовой подделки запроса, как описано в разделе 10.12.
Безопасно ли использовать параметр “state”, который я генерирую (uuid/v4
) в запросе авторизации OAuth2, помимо защиты от CSRF, для идентификации пользователя в обратном вызове провайдера в процессе авторизации? Таким образом, делая поток oauth2 “безсостоянии” и не требуя “липких сессий” для балансировщика нагрузки.
В настоящее время, когда пользователь начинает поток OAuth2 (посещает страницу входа), я создаю уникальный auth-request-id
и state
для него и сохраняю это в Redis и отправляю auth-request-id
в cookie.
После того, как пользователь входит в систему у провайдера (Google или Facebook) в запросе обратного вызова, я пытаюсь найти сессию пользователя из cookie auth-request-id
в Redis и проверить, существует ли сессия и соответствует ли полученное state
тому, что я отправил (против атак CSRF).
Интересно, могу ли я пропустить создание cookie auth-request-id
и идентифицировать пользователя в обратном вызове по state
? Учитывая логику, если соответствующее state
не может быть найдено в Redis, предполагаем, что состояние недействительно и все хранимые в Redis state
имеют время истечения 5 минут.
Я считаю, что вы не можете сделать это безопасно.
Злоумышленник может свободно получать перенаправления, используя ваше приложение. Теперь, если ему удастся заставить ничего не подозревающую жертву открыть адрес перенаправления, тогда жертва увидит, что ваше приложение запрашивает доступ. Если он предоставит доступ, его перенаправят обратно к вам, и если вы используете только состояние для его идентификации, то вы просто назначили ресурсы жертвы учетной записи злоумышленника в вашем приложении.
Ответ или решение
Может ли параметр "state" в OAuth2 служить для идентификации пользователя без сессионных куки?
OAuth2 — это широко используемый протокол авторизации, который позволяет пользователям предоставлять третьим лицам доступ к своим данным, не делясь паролями. Основной задачей в этом процессе является обеспечение безопасности и предотвращение возможных атак, таких как CSRF (Cross-Site Request Forgery). В данном контексте возникает вопрос: можно ли безопасно использовать параметр "state" для идентификации пользователя и исключить необходимость в сессионных куках при прохождении OAuth2 потока?
Параметр "state" и его назначение
Согласно спецификации OAuth2 (RFC 6749), параметр "state" рекомендуется использовать для поддержания состояния между запросом и обратным вызовом. Он позволяет клиенту и серверу авторизации обеспечивать целостность запроса и оценивать, был ли он скомпрометирован, например, через CSRF-атаки. Поскольку "state" является непрозрачным значением, оно может быть использовано для передачи информации, необходимой для идентификации сессии.
Использование состояния для идентификации пользователя
Использование уникального значения "state" (например, UUIDv4), созданного на стороне клиента, для идентификации пользователя на этапе обратного вызова может показаться логичным решением для реализации "безстатусной" архитектуры. Однако следует учитывать несколько важных аспектов:
-
Проблема безопастности: Если злоумышленник сможет инициировать авторизационный запрос к вашему приложению и заполучить "state", он сможет перенаправить пользователя в свой профиль, таким образом, злоумышленник может завладеть ресурсами пользователя. Если "state" используется в качестве единственного средства идентификации, это может привести к присвоению ресурсов пользователя учетной записи злоумышленника.
-
CSRF-защита: Параметр "state" действительно предоставляет защиту от CSRF, поскольку сервер авторизации возвращает именно то значение "state", которое был отправлен в первоначальном запросе. Однако это не является альтернативой надежному способу идентификации пользователя, так как "state" может быть как создано, так и перехвачено злоумышленником.
-
Статус и сессии: Если вы решите не использовать куки для идентификации пользователя, а полагаться только на "state", вам нужно обеспечить надёжное хранилище и логику проверки состояния. Хранение состояний в Redis с коротким временем жизни (например, 5 минут) — это шаг в правильном направлении, однако, риски, связанные с безопасностью, сохраняются.
Вывод
В свете этих моментов, несмотря на возможность использования параметра "state" как механизма идентификации, это не является безопасным и рекомендуемым решением. Завися от параметра "state" для идентификации пользователя, вы открываете возможности для потенциальных атак, которые могут привести к компрометации аккаунтов и ресурсов пользователей.
Рекомендуется сохранить подход с использованием как "state", так и дополнительного идентификатора сессии (например, "auth-request-id"), который мог бы безопасно идентифицировать пользователя и предотвратить злоупотребления. Это обеспечит большую степень безопасности и защитит ваши системы от возможных уязвимостей.
Таким образом, для создания безопасного и надежного потока авторизации в OAuth2 важно учитывать целый ряд факторов, включая потенциальные угрозы безопасности и способы их минимизации. Сессионные куки остаются важным аспектом при реализации защищенной авторизации и их нельзя игнорировать.