Сегодня, в мире социальных медиа, каждый из нас использует десятки приложений и вебсайтов ежедневно. Oauth 2.0 призван упростить процесс авторизации и, как следствие, сделать жизнь пользователей проще и безопаснее. Возникает вопрос — каким образом?
Oauth 2.0 — что это такое?
Возьмем обычную ситуацию: вы открываете какой-либо сайт, выбираете, какой провайдер данных и какой конкретно аккаунт использовать, даете разрешение на использование данных (если необходимо) и работаете дальше от имени владельца этого аккаунта. Вы не вспоминаете пароль, не тратите время на утомительную регистрацию — все это сводится к нескольким кликами.
Eстественно, для этого у Вас должна быть учетная запись у выбранного провайдера.
Термин «провайдер» подразумевает сервис, который владеет данными пользователя и, с разрешения пользователя, предоставляет сторонним сервисам (клиентам) безопасный доступ к этим данным. Приложение, желающее получить данные пользователя — это клиент.
Для примера взята форма логина/регистрации на Aliexpress. В данном случае на форме присутствует выбор из нескольких провайдеров — Google, Facebook, Вконтакте и Twitter.
Вы жмете «войти через Facebook» или «войти через Google», Вас перенаправляют на страницу выбора аккаунта, Вы выбираете свою учетную запись и все — Вы уже залогинились.
Спецификация OAuth 2.0 определяет протокол делегирования, который предоставляет клиентам безопасный доступ к ресурсам пользователя на сервисе-провайдере. Такой подход избавляет пользователя от необходимости вводить пароль за пределами сервиса-провайдера: весь процесс сводится к нажатию кнопки «Согласен предоставить доступ к ...». Идея в том, что имея один хорошо защищенный аккаунт, пользователь может использовать его для аутентификации на других сервисах, не раскрывая при этом своего пароля.
В отличие от OpenID, OAuth 2.0 может использоваться и для авторизации. То есть, позволяет выдать права на действия, которые сам сервис-клиент сможет производить от лица владельца аккаунта. При этом сам владелец после авторизации может вообще не участвовать в процессе выполнения действий, например, сервис по продаже билетов самостоятельно создает мероприятие в календаре пользователя, или игра размещает на стене в Facebook отчет об очередном завоеванном кубке.
Общая схема OAuth 2.0 :
- Клиент запрашивает авторизацию у владельца ресурса.
- Клиент получает грант авторизации.
- Клиент запрашивает токен доступа путем аутентификации с помощью сервера авторизации и предоставление гранта авторизации.
- Сервер авторизации аутентифицирует клиента, проверяя грант авторизации и, если он действителен, выдает токен доступа (access token) и рефреш токен (refresh token).
- Клиент запрашивает защищенный ресурс у провайдера и аутентифицируется, представляя токен доступа.
- Провайдер проверяет токен доступа и, если он действителен, обслуживает запрос.
Итак, мы видим, что конечная цель — это получить access и refresh токены. Дальше клиент общается с провайдером данных, пока у access токена не кончится срок годности. Затем, чтобы получить доступ к данным провайдера снова, клиенту нужно воспользоваться refresh токеном и отправить запрос на генерацию новой пары access/refresh токенов.
Зачем вообще нужен refresh токен?
Представим ситуацию, когда некто завладел Вашим access токеном и получил доступ к защищенным данным. Именно поэтому у токенов есть срок годности. У access токена он обычно маленький — от нескольких секунд, до нескольких дней, у refresh токена — побольше. Так вот доступ к данным у злоумышленника будет до тех пор, пока токен доступа не протухнет. Допустим, этот некто завладел еще и refresh токеном и воспользовался им раньше чем Вы, тем самым получив новый access токен. В таком случае Вы не можете получить данные с провайдера, но для решения этой проблемы Вам будет достаточно разлогиниться и залогиниться заново — и все! Все старые токены станут недействительными или удаляться (зависит от реализации). После этой процедуры Вы получаете новые access/refresh токены и можете спокойно продолжить работу, а плохой парень, со старыми токенами, остался с носом.
Преимущества и недостатки OAuth 2.0
Из плюсов OAuth 2.0 протокола можно выделить следующее:
- Обращение к ресурсам происходит по HTTP/HTTPS с указанием токена в заголовках. Это позволяет использовать OAuth практически в любых решения: мобильных и десктоп приложениях, сайтах, и даже в плагинах для браузеров.
- Возможность авторизации пользователя.
- Популярность - большинство компаний используют его в своих API.
- Простота реализации и большое количество “литературы”.
- Наличие готовых решений, которые можно изменять под свои нужды.
Из минусов:
- Нет единого установленного формата, вследствие чего на каждый сервис нужно иметь отдельную реализацию.
- При аутентификации иногда приходится делать дополнительные запросы для получения даже минимальной информации о пользователе. Решается использованием jwt токена, но далеко не все сервисы его поддерживают.
- При краже токена у злоумышленника на какое-то время появляется доступ к защищенным данным. Для минимизации данного варианта можно используют токен с подписью.
Реализацию OAuth 2.0 подхода на php можно найти на GitHub в нескольких популярных бандлах:
Немного о JWT
JSON Web Token — открытый стандарт для создания токена в json формате. Такой токен состоит из трех частей, разделенных точками: заголовок(header), набор полей (payload) и сигнатура. Первые два блока представлены в json-формате и дополнительно закодированы. Для заголовка есть один обязательный ключ — alg, указывающий алгоритм подписи. Набор полей payload содержит произвольные пары ключ/значения. Также существуют необязательные зарезервированные ключи (ознакомиться).
Сигнатура может генерироваться при помощи как симметричных алгоритмов шифрования, так и асимметричных. Кроме того, существует отдельный стандарт, описывающий формат зашифрованного JWT-токена.
Пример
У нас есть некий ключ SECRET_KEY, его знает только сервер и приложение — клиент (получает его во время установки).
$SECRET_KEY="stFalcon";$header='{"typ":"JWT","alg":"HS256"}';$payload='{"sub":"1234567890","name":"alex","admin":true}';$unsignedToken= \sprintf("%s.%s",base64_encode($header),base64_encode($payload));$signature=hash_hmac('sha256',$unsignedToken,$SECRET_KEY);</p></ol> $tokenEncoded= \sprintf("%s.%s.%s",base64_encode($header),base64_encode($payload),base64_encode($signature));
В результате имеем готовый токен -
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImFsZXgiLCJhZG1pbiI6dHJ1ZX0=.MTI5MGZmYTkwMGM2YmE0ODIzNGQ2ZGI4OGYxZTM2NGY5Y2VhYzExN2NiZGNjODA0YmNhN2NhNmM1ZWUzMDQ3NA==
Теперь проверим токен на валидность -
$tokenDecodedArr=explode('.',$tokenEncoded); $externalHeader=$tokenDecodedArr[0];$externalPayload=$tokenDecodedArr[1];$externalSignature=$tokenDecodedArr[2]; if(base64_decode($externalSignature)===hash_hmac('sha256', \sprintf("%s.%s",$externalHeader,$externalPayload),$SECRET_KEY)){echo'matched';}else{echo'don’t mathe';}
Таким образом мы проверяем совпадают ли подписи, если да — JWT валидный, т.е. пришел от проверенного источника. Если подписи не совпадают, значит что-то пошло не так — возможно, это является признаком потенциальной атаки.
В итоге используя jwt мы получаем дополнительную ступень защиты от кражи своих данных, и возможность передавать некий набор информации без дополнительных запросов.
Заключение
Подведем итог. OAuth 2.0 - это простой протокол авторизации, основанный на HTTP, что дает возможность применять его практически на любой платформе. Он имеет хорошую документацию, и большинство крупных площадок его поддерживают. Так что если вы решили использовать этот протокол в своем проекте — это хороший выбор.