Авторизация с помощью OAuth 2.0 на Go
Разбор OAuth 2 в доступной форме с примером реализации на Go,
18К открытий20К показов
Вячеслав Аврамёнок
младший разработчик компании Selectel
С появлением большого числа веб-сервисов, возникла необходимость в предоставлении ресурсов одного сервиса другому. Самое первое реализованное решение заключалось в предоставлении пользователем логина и пароля сервису А, чтобы тот мог получить данные от сервиса В. Однако такое решение имеет следующий ряд проблем и ограничений:
- Сервису А необходимо хранить логин и пароль пользователя у себя, более того, пароль хранится в незашифрованном виде.
- Нельзя выбрать подмножество ресурсов, а также ограничить время их доступности.
- Пользователь не может выборочно запретить сервису доступ к его ресурсам. При изменении логина или пароля все сервисы потеряют доступ.
- Взлом одного из сервисов приведет к утечке логина и пароля пользователя, и, следовательно, доступу к приватным данным другого сервиса.
Таким образом, для решения обозначенных выше проблем, была предложена спецификация OAuth, реализовав которую, становится возможным безопасное получение сторонним сервисом ограниченного доступа к ресурсам другого.
Примечание Статья носит сугубо информативный характер, и не преследует цели максимально подробно изложить материал по теме — для этого есть документация. Следует упомянуть что статья появилась на свет по причине изучения данного вопроса самим автором. Если вы не в курсе что такое OAuth, то ниже вашему вниманию представлен материал, который я попытался обобщить и изложить в доступной форме.
Существует две версии спецификации: OAuth 1.0 и OAuth 2.0, которые, к слову, обратно несовместимы. Первая версия была опубликована в 2007 году, и представляет собой документ с рекомендациями по делегированию ресурсов стороннему сервису без раскрытия логина и пароля пользователем, в то время как вторая версия (2012 год) уже является интернет стандартом, учитывает недостатки первой версии, и расширяет возможные сценарии использования (выборочный доступ к ресурсам, 4 вида авторизации, использование нативных приложений, refresh token и т.д.). Когда говорят об OAuth, то, как правило, имеется в виду именно вторая версия, т.к. она чаще всего используется, и далее поговорим о ней подробнее.
Действующие лица
В спецификации OAuth 2.0 выделяют следующие роли:
- Client. Сервис (приложение), желающий получить доступ к пользовательским данным.
- Resource Server. Сервис, владеющий пользовательскими данными.
- Authorization Server. Сервис, предоставляющий пользователю интерфейс выбора дать или нет доступ к ресурсам стороннему сервису.
- Resource Owner. Пользователь, дающий доступ к ресурсам.
Рассмотрим работу OAuth с точки зрения Client как с наиболее частым кейсом использования разработчиками, а подробности реализации Authorization Server — это уже документация.
Общий флоу работы с OAuth
- Пользователь делает запрос на предоставление Client доступа к приватным данным другого сервиса.
- Client генерирует и отправляет пользователю ссылку, которая перенаправит его на Authorization Server стороннего сервиса.
- Пользователь аутентифицируется на Authorization Server введя логин и пароль, либо ничего не вводя, т.к. в браузере уже будет активная сессия.
- Authorization Server покажет пользователю форму в которой спросит разрешается ли предоставить доступ к перечисленным ресурсам стороннему сервису.
- Если пользователь соглашается, то Authorization Server делает редирект пользователя вместе с токеном авторизации (или кодом авторизации) на эндпоинт Client (см. Регистрация приложения).
- Client читает предоставленный токен доступа (или читает код авторизации и меняет его на токен доступа через специальный эндпоинт на Authorization Server), затем обращается с этим токеном к Resource Server.
- Resource Server проверяет токен доступа и отправляет приватные данные пользователя.
- Client получает данные, пользователь теперь может с ними взаимодействовать.
Вообще, при получении токена доступа также может приходить refresh token (т.е. это на усмотрение Authorization Server), задача которого — получение новых токенов доступа, если старые стали невалидными. Стоит отметить, что все сетевые операции должны выполняться с использованием HTTPS.
Регистрация приложения
Перво-наперво необходимо зарегистрировать Client на Authorization Server. Во время регистрации необходимо заполнить такую информацию как имя, веб-сайт, лого приложения и т.д. Также обязательным элементом регистрации является указание ссылки URI куда Authorization Server будет делать редирект пользователя после апрува на выдачу доступа к его ресурсам, расположенным на Resource Server. После регистрации будут выданы Client ID и Client Secret, которые используются в процессе получения авторизации.
Виды авторизации пользователя
Authorization Code
Приложение (Client) делает редирект пользователя на Authorization Server, где пользователь аутентифицируется и ему отображается интерфейс с выбором — дать или нет доступ приложению на перечисленные ресурсы. В случае апрува выдачи доступа, пользователь редиректится обратно в приложение вместе с кодом авторизации по ссылке URI, которая задавалась в процессе регистрации Client на Authorization Server. Далее код авторизации обменивается на токен доступа с помощью которого происходит взаимодействие с ресурсами пользователя. Сразу возникает вопрос: зачем вообще нужен код авторизации, почему не вернуть токен доступа сразу? Фишка кода авторизации в том, что с его помощью токен доступа получает безопасный Client, без посредника в виде браузера пользователя (который установлен на устройстве с вирусами, к примеру). Является рекомендуемым способом авторизации.
Implicit
Данная авторизация отличается от предыдущей лишь тем, что в ней отсутствует код авторизации и токен доступа возвращается сразу. Необходим такой упрощенный сценарий для случаев когда Client реализован в браузере или мобильном приложении, т.е. на стороне пользователя. Такой подход увеличивает отклик приложения, но является небезопасным по причине упомянутой выше.
Resource owner password credentials
Client запрашивает у пользователя логин и пароль, а затем обменивает их на токен доступа. Такой вариант авторизации должен использоваться при достаточном доверии между пользователем и Client (например, если Client – стандартное приложение ОС – first party app), или если других доступных вариантов авторизации нет. Хотя в этом подходе и раскрываются логин и пароль пользователя, Client использует их единожды при получении токена доступа, таким образом исключается необходимость их хранения.
Client credentials
Используется в случаях когда Client взаимодействует с Resource Server от своего имени, т.е. Client является Resource Owner(например, приложение обновляет статистику о количестве активных пользователей).
Получение авторизации
Рассмотрим наиболее часто встречающийся кейс: имеется клиент-браузер и веб-сервер — последний находится на сервере к которому нет публичного доступа. Это значит что веб-сервер может безопасно использовать Client Secret, полученный на этапе регистрации приложения. Теперь по порядку:
Создание ссылки, которая перенаправит пользователя на Authorization Server:
response_type=code
— говорит о том, что сервер ожидает получить код авторизации.client_id
— значение полученное во время регистрации приложения.redirect_uri
— ссылка, на которую, после успешной авторизации, Authorization Server делает редирект пользователя вместе в токеном (или кодом доступа).scope
— один и больше значений, обозначающих к каким ресурсам пользователя необходимо иметь доступ. Необходимые значения берутся из соответствующей документации на Authorization Server.state
— случайная строка, которую Authorization Server должен вернуть обратно наredirect_uri
, её необходимо будет проверить на равенство. Нужно это для защиты от CSRF (redirect_uri
ведь не защищен, а это значит что недобросовестное лицо может собрать uri со своим токеном или кодом доступа, сделать так, чтобы другой пользователь перешел по этому uri, и тогда пользователь будет работать с чужими ресурсами, а здесь уже и приватные данные можно засветить, к примеру).
Если пользователь согласился предоставить доступ к своим ресурсам, то Authorization Server сделает редирект обратно на Client.
code
— Authorization Server возвращает код авторизации.state
— Authorization Server возвращает то же значение, что было передано в шаге 1.
Необходимо сравнить переменную state
чтобы быть уверенным в валидности запроса.
Client меняет код авторизации на токен доступа делая POST запрос:
grant_type=authorization_code
— вид авторизации.code
— код авторизации, полученный на шаге 2.redirect_uri
— должен быть таким же как в шаге 1.client_id
— значение полученное во время регистрации приложения.client_secret
— значение полученное во время регистрации приложения.
В случае успеха Authorization Server отвечает токеном доступа и временем в течении которого токен валиден, иначе — ошибкой.
Пример авторизации в vk с помощью OAuth, взаимодействие с ресурсами пользователя
Применим полученные знания на практике. Задача: делегировать стороннему сервису доступ к базовой информации пользователя в vk с использованием OAuth.
Решение:
Регистрируем приложение (сторонний сервис) в разделе для разработчиков Указываем redirect_uri
в настройках приложения.
Далее развернем веб-сервер и имплементируем для него пару эндпоинтов: один для редиректа пользователя на Authorization Server, а другой для обработки зарегистрированного выше redirect_uri
. Задачу будем решать на Go.
Создадим следующие переменные:
Собираем ссылку для редиректа пользователя на Authorization Server:
Принимаем ответ от Authorization Server’а:
Запускаем веб-сервер:
Обращаемся на localhost:8080/, переходим по сгенерированной ссылке на Authorization Server, получаем следующий результат:
Резюме
В статье были разобраны основы спецификации OAuth, а также решена тестовая задача по делегирования прав доступа пользовательской информации vk стороннему сервису. Для большего понимания OAuth 2.0 рекомендуется почитать соответствующий white paper. Здесь можно найти код веб-сервиса разработанного выше.
Источники
18К открытий20К показов