Как сделать свой oauth сервер
Для примера рассмотрим полный цикл получения доступа к данным, начиная от регистрации новой интеграции.
При этом мы будем рассматривать прямую работу с API авторизации, но вы можете либо воспользоваться нашей готовой
библиотекой на PHP для упрощения разработки,
либо готовыми библиотеками сторонних вендоров, которые можно найти по ссылке.
Мы разрабатывали авторизацию, основываясь на протоколе oAuth 2.0,
поэтому вы можете найти в открытых источниках много примеров и документацию,
описывающих взаимодействие и логику выполнения запросов.
Оглавление
Все начинается с того, что вам необходимо зайти в раздел Интеграции того аккаунта,
в котором вы будете осуществлять поддержку интеграции в будущем. Обратите внимание:
- Именно за этим аккаунтом будет закреплена Интеграция.
Это означает, что любой из администраторов этого аккаунта сможет управлять интеграцией и получит доступ к общим ключам приложения.
Подробнее о терминах можно прочесть здесь.
По сути этот аккаунт мы будем считать аккаунтом разработчика.
Если вы разрабатываете публичную интеграции, необходимо ознакомиться с требованиями. - Для создания интеграции вам необходимо обладать правами администратора аккаунта
После нажатия на кнопку Создать Интеграцию, в появившейся форме, вам необходимо указать Название интеграции,
выбрать требуемые доступы и указать описание.
Также необходимо указать Redirect URI – url страницы получения токенов и загрузить логотип интеграции.
Кроме того, есть возможность указать url для хука об отключении интеграции – на него придет хук,
когда интеграция будет отключена пользователем. Поле для хука об отключении является необязательным.
- Название интеграции (не более 255 символов) – отображается на странице интеграций, модальном окне для предоставления доступов, а также участвует в поиске по странице интеграций.
- Описание интеграции (не более 65000 символов) – отображается в модальном окне интеграции в аккаунте пользователя. Допускается использование html верстки.
- Ссылка для перенаправления – ссылка на ваш сайт, который будет обрабатывать работу с ключами. Важно, что домен должен быть защищен SSL сертификатом, если вы планируете использовать интеграцию более, чем в одном аккаунте. Также мы периодически проверяем доступность домена, как обязательное условие для работы интеграции.
- Ссылка для хука об отключении интеграции – на этот адрес будет отправлен GET-запрос при отключении интеграции пользователем. В запросе будет содержаться 2 параметра account_id и client_id.
- Предоставить доступ – минимальный набор необходимых разрешений для работы интеграции. Подробнее про разрешения можно прочитать в статье.
- Иконка интеграции (400х272 jpeg/jpg/png/gif) – отображается в списке интеграций, а также в окне запроса доступа у пользователя
- Контроль дублей – галку необходимо ставить, если ваша интеграция поддерживает Контроль дублей. После установки галки, интеграция будет доступна в настройках контроля дублей.
- Множественные источники – галку необходимо ставить, если ваша интеграция сама управляет источниками через API. Если галка установлена, amoCRM не будет создавать источники по-умолчанию, интеграция сама должна будет создать все необходимые ей источники.
Кроме этих пунктов, администраторам аккаунта, в котором создана интеграция, будут доступны: ID интеграции, секретный ключ интеграции, код авторизации (после включения интеграции).
После заполнения полей вам необходимо сохранить интеграцию.
После этого новая интеграция будет создана и открыто модальное окно созданной интеграции. В открывшемся модальном окне, на вкладке ключи будут отображены необходимые ключи.
Обратите внимание, что Secret key и Integration ID привязаны к интеграции и будут показаны только в вашем аккаунте разработчика.
Получение Authorization code
Напомним, что код авторизации является временным ключом, который действует только 20 минут.
C его помощью вам необходимо в течении этого времени получить refresh token и access токен.
Он является временным, т.к. может быть перехвачен, но в случае перехвата злоумышленник не сможет с ним ничего сделать,
если вы не сообщите ему ключи приложения, известные только администраторам аккаунта, в котором создана интеграция.
Получить Authorization code можно тремя способами:
Вы можете упростить разработку при использовании способа получения ключа через GET-параметры, используя готовую Кнопку amoCRM.
Полная логика способа получения ключа через GET-параметры заключается в следующем:
Пример обработки авторизации, если был передан параметр post_message
При переданном GET-параметре mode со значением post_message в окно предоставление доступов – перенаправление произойдет в самом окне.
Ниже рассмотрим пример общения окна предоставления доступов и основного окна с использованием функции postMessage.
Код ниже размещен в основном окне:
Код ниже будет отдан в модальное окно вашим backend сервером при переходе на Redirect URI:
После отработки кода выше, основное окно узнает результат. Рекомендуем закрывать модальное окно автоматически,
как это сделано в примере, чтобы у пользователя не возникла путаница в окнах.
Обмен кода авторизации на access token и refresh token
Получив Authorization code, вам необходимо сделать запрос на специальный метод /oauth2/access_token, описанный ниже.
В ответ вы получите пару Access и Refresh token, а также время в секундах, через которое токен истекает.
Разбираемся, как работает протокол OAuth 2.0 и OpenID Connect. Почему Authorization Code Grand лучший способ получения access token.
Если коротко OAuth 2.0 — протокол авторизации, позволяющий выдать одному сервису (приложению) права на доступ к ресурсам пользователя на другом сервисе. Протокол избавляет от необходимости доверять приложению логин и пароль, а также позволяет выдавать ограниченный набор прав, а не все сразу.
В этой статье рассмотрим историю возникновения и схему работы. Разберемся в чем отличие OAuth 2.0 от OpenID Connect и что такое SSO.
История возникновения OAuth
Авторизацией через социальные сети никого уже не удивишь. Нажимаешь кнопку соц сети, вжух и ты авторизовался на новом сайте. Сайт получил твоё ФИО, фотку и прочие данные. Но так было не всегда.
С помощью этого стандарта вы позволяете приложению считать данные или использовать функции другого приложения от вашего имени, не сообщая ему свой пароль. Класс!
OAuth 1.0 не используется. Забудьте о нем. Используйте OAuth 2.0
Главным недостатком OAuth 1.0 была слишком большая сложность данной версии.
Начнем разбор OAuth 2.0 с ролей. Всего есть 4 роли:
- Владелец ресурса.
- Клиент.
- Сервер ресурсов.
- Авторизационный сервер.
Далее мы рассмотрим каждую из ролей.
Сервер ресурсов
На сервере ресурсов лежат ваши данные. В случае с примером выше ваши контакты Gmail это ресурс, а лежат они на серверах Gmail.
Клиент
Клиент это сервис, которому требуется доступ к вашим ресурсам. Например, Facebook требуется доступ к контактам Gmail.
Авторизационный сервер
В данном примере он принадлежит Google, так как он хранит ваши данные.
Базовая схема протокола
Вернемся к нашему примеру про Facebook и Gmail. На анимации ниже, я постарался схематично изобразить, как реализовать этот пример правильно с помощью Oauth2. Стоит учитывать, что у Google есть свой сервер авторизации, который отвечает за авторизацию на любом сервисе Google. Поэтому Gmail только хранит ресурсы, но не отвечает за авторизацию.
Весь смысл в том, что Клиент должен получить каким-то образом от авторизационного сервера access_token . Способов этих четыре, о них мы поговорим дальше. Используя этот access_token Клиент может использовать его в запросах к Серверу ресурсов, чтобы получать какие-то данные.
Это строка, которая является альтернативой логину и паролю.
Особенности Access Token:
- Ограниченное время жизни.
- Его можно отозвать. Если есть подозрение, что токен украли, то мы просто запрещаем получать данные с помощью этого токена.
- Компрометация токена не значит компрометирование логина и пароля. Из токена никак не получить логин и пароль.
- По токену может быть доступна только часть данных (scope). Клиент запрашивает список разрешений, которые необходимы ему для работы, а Владелец ресурсов решает выдать такие права или нет. Например, можно выдать права только на просмотр списка контактов, тогда читать письма или редактировать контакты будет нельзя.
Помимо access_token Авторизационный сервер может выдавать также refresh_token. Это токен, который позволяет запросить новый access_token без участия Владельца ресурсов. Время жизни у такого токена намного больше access_token и его потеря гораздо серьезнее.
Не все клиенты могут гарантировать сохранность client_secret , поэтому он есть не у всех. Например, SPA без бэкенда, теоретически достать оттуда можно что угодно.
Существует возможность регистрировать клиентов динамически: RFC 7591 и RFC 7592.
Способы получения Access Token
Всего есть 4 способа:
- По авторизационному коду (Authorization Code Grand). Самый сложный и самый надежный способ.
- Неявно (Implicit)
- По логину и паролю пользователя (Resource Owner Password Credential). Только для безопасных клиентов, заслуживающих полного доверия.
- По данным клиента (Client Credentials). Получаем токен по client_id и client_secret .
Client Credentials
Начнем разбор с самой простой схемы. Этот способ придуман для межсерверного взаимодействия. У нас есть два сервера API1 и API2, и им надо как-то общаться.
2. Взамен API 1 получает access_token , с помощью которого может обратиться к API 2.
3. API 1 обращается к API 2.
4. API 2 получает запрос с access_token и обращается к авторизационному серверу для проверки действительности переданного токена (RFC 7662).
Resource Owner Password Credential
Эта схема не рекомендуется к использованию! В стандарте так и написано, если вы никакие другие схемы не можете сделать, то используйте эту.
- Владелец ресурсов передает свой логин и пароль Клиенту.
- Клиент отправляет Авторизационному серверу логин и пароль клиента, а так же свой client_id и client_secret .
3. Если предоставленные пользователем учетные данные успешно аутентифицированы, сервер авторизации вернет ответ application/json , содержащий access_token :
Authorization Code Grand
Является одним из наиболее распространённых типов разрешения, поскольку он хорошо подходит для серверных приложений, где исходный код приложения и секрет клиента не доступны посторонним.
Этот способ рекомендуемый. Используйте его, и только если это невозможно, посмотрите на другие способы. Исключением является межсерверное общение.
- Пользователь на сайте нажимает кнопку авторизации, например через Facebook.
- Происходит редирект на авторизационный сервер.
- Если активной сессии нет, то Пользователь должен залогиниться. Если активная сессия есть, то просто подтвердить авторизацию.
Пример авторизационного запроса
- response_type - Обозначает тип учетных данных, которые возвращает авторизационный сервер. Для этого способа значение должно быть code .
- redirect_uri - URL-адрес, на который авторизационный сервер будет перенаправлять браузер после авторизации пользователя. Код авторизации будет доступен в параметре code .
Так как code попадает в браузер и ничем не защищен, то это точка уязвимости. Поэтому на авторизационный код накладываются следующие ограничения:
- Код одноразовый
- Время жизни кода очень мало
5. Теперь, когда у вас есть код авторизации, вы должны обменять его на токены. Используя извлеченный код авторизации из предыдущего шага, вам нужно будет выполнить POST на URL-адрес токена.
Implicit Grant
Теперь у нас сайт без бэкенда - SPA.
Так как access_token попадает в браузер, то существует возможность его достать.
OpenID Connect
OAuth 2.0 разработан только для авторизации — для предоставления доступа к данным и функциям от одного приложения другому. OpenID Connect (OIDC) — это тонкий слой поверх OAuth 2.0, добавляющий сведения о логине и профиле пользователя, который вошел в учетную запись.
OpenID Connect позволяет реализовывать сценарии, когда единственный логин можно использовать во множестве приложений, — этот подход также известен как single sign-on (SSO)
Поток (flow) OpenID Connect выглядит так же, как и в случае OAuth 2.0. Единственная разница в том, что в первичном запросе используемый конкретный scope — openid, — а Клиент в итоге получает как access_token , так и id_token .
ID Token — это особым образом отформатированная строка символов - JSON Web Token или JWT. Сторонним наблюдателям JWT может показаться непонятной абракадаброй, однако Клиент может извлечь из JWT различную информацию, такую как ID, имя пользователя, время входа в учетную запись, срок окончания действия ID Token’а, наличие попыток вмешательства в JWT.
Эта статья посвящена детальному разбору JWT и его возможностей. Мы изучим структуру токена и построим его с нуля. Затем рассмотрим наиболее распространенные способы использования.
В случае OIDC также имеется стандартный способ, с помощью которого Клиент может запросить дополнительную информацию о пользователе от Сервера авторизации, например, адрес электронной почты, используя access_token .
Заключение
На этой странице вы найдёте информацию о реализации авторизации по протоколу OAuth2 на вашем проекте через сервис Аккаунты Ely.by. Реализация этого протокола позволяет вашим пользователям производить авторизацию с использованием своего аккаунта Ely.by.
Для начала вам необходимо создать новое приложение. Выберите тип приложения Веб‑сайт. В качестве адреса переадресации можно указать только домен, но для повышения безопасности лучше использовать полный путь переадресации. Примеры допустимых адресов:
После успешного добавления приложения вы попадёте на страницу со списком всех ваших приложений. Кликнув по названию приложения вы увидите его идентификатор clientId и секрет clientSecret . Они буду использоваться на следующих шагах.
Инициализация авторизации¶
Обязательное. ClientId, полученный при регистрации.
Обязательное. Адрес обратной переадресации, совпадающий с адресом, указанным при регистрации приложения
Обязательное. Тип ответа. На данный момент поддерживается только code .
Обязательное. Перечень разрешений, доступ к которым вы хотите получить, разделённые пробелом. Смотрите все доступные права в разделе ниже.
Случайно сгенерированная строка. Используется для увеличения безопасности в качестве идентификатора сессии. Будет возвращена в неизменённом виде после завершения авторизации.
यो अनुप्रयोग विवरण
Если ваше приложение доступно на нескольких языках, то используя это поле вы можете переопределить стандартное описание в соответствии с предпочтительным языком пользователя.
consent или select_account
Принудительно отобразить запрос прав ( consent ) или принудительно запросить выбор аккаунта ( select_account ).
erickskrauch или [email protected]
Если у пользователя есть несколько аккаунтов, то указав этот в этом параметре username или E-mail пользователя вы автоматически выберете аккаунт за него. Это полезно в случае повторного входа, когда токен истёк.
account_info
Получение информации о пользователе.
account_email
В ответе на запрос информации о пользователе будет также присутствовать его email.
offline_access
Вместе с access_token вы также получите и refresh_token . Смотрите подробнее соответствующем разделе.
minecraft_server_session
access_token можно будет использовать в качестве сессии для Minecraft.
Сформировав ссылку, разместите её в вашем шаблоне:
По нажатию на ссылку, пользователь попадёт на нашу страницу авторизации, откуда после он будет перенаправлен обратно по адресу, указанному в параметре redirect_uri .
Обратная переадресация выполняется в виде ?code= авторизации>&state= для успешной авторизации и ошибки>&error_message= ошибки> для неудачной.
Пример успешного и неудачного редиректов:
Обмен кода на ключ¶
После получения кода авторизации ( auth_code ), вам необходимо обменять его на ключ авторизации ( access_key ). Для этого необходимо выполнить POST запрос на URL:
И передать туда следующие параметры:
ClientID, полученный при регистрации приложения.
ClientSecret, полученный при регистрации приложения.
Точный адрес, использованный для переадресации пользователя.
В данном случае указывается authorization_code .
Пример реализации обмена на PHP:
Пояснение к коду:
Сначала мы объявляем переменную $oauthParams , в которую заносим значения, полученные после регистрации приложения.
Затем проверяем, не возникла-ли ошибка. В этом случае сразу же прерываем выполнение.
Формируем POST запрос к форме обмена code на access_token , передавая необходимые поля.
Выполняем запрос, получаем ответ, переводим его из JSON в ассоциативный массив.
Ответ сервера¶
В случае успешного запроса в теле ответа будет находиться результат обмена кода авторизации на access_token . Данные являются JSON документом и могут быть легко интерпретированы средствами используемого языка программирования.
Тело JSON документа содержит следующие поля:
На этом процедура авторизации закончена. Полученный access_token может быть использован для получения информации о пользователе и взаимодействия с нашим API.
Получение информации о пользователе¶
Для передачи access_token используется заголовок Authorization со значением Bearer .
Пример реализации получения информации о пользователе на PHP:
В ответ вы получите JSON документ со следующим содержимым:
Обратите внимание, что поле email будет присутствовать лишь в том случае, когда был запрошен scope account_email .
В ходе дальнейшего развития сервиса, количество возвращаемых полей может увеличиться, но уже существующие останутся теми же.
Обновление токена доступа¶
Если при выполнении авторизации вами было запрошено право на получение scope offline_access , то вместе с access_token вы также получите и refresh_token . Данный токен не истекает и может быть использован для получения нового токена доступа, когда он истечёт.
ClientID, полученный при регистрации приложения.
ClientSecret, полученный при регистрации приложения.
Те же scope, что были запрошены и при получении начального токена доступа. Попытка запросить большее количество прав приведёт к ошибке.
Непосредственно токен, полученный вместе с начальным токеном доступа.
Пример реализации обновления токена доступа на PHP:
В качестве ответа будет точно такое же тело, какое было получено в результате обмена кода на ключ доступа. Поле refresh_token будет отсутствовать.
Готовые библиотеки¶
Более простым способом будет использовать уже готовую библиотеку, которой будет необходимо передать лишь регистрационные параметры. Ниже перечислены библиотеки для различных языков программирования. Вы можете дополнить этот список своей библиотекой.
PHP:
Ruby:
Возможные ошибки¶
Ниже приведены стандартные ошибки, которые вы можете получить в случае неправильной передачи данных на сервер авторизации. Если вы столкнулись с ошибкой, не описанной в этой документации, пожалуйста, сообщите о ней через форму обратной связи.
Ошибки при инициализации авторизации¶
Этот раздел описывает ошибки, отображаемые при переадресации пользователя с вашего сайта на нашу страницу инициализации авторизации.
Данная ошибка означает, что вы передали не все необходимые параметры. Чтобы решить эту ошибку просто добавьте недостающий параметр.
Данная ошибка означает, что вы передали неподдерживаемый тип response_type . На данный момент поддерживается только значение code .
Ошибка указывает на то, что было запрошено неизвестный scope . Убедитесь, что вы запрашиваете поддерживаемые права.
Ошибки при обмене кода на ключ¶
В случае возникновения ошибки вместо ожидаемого ответа с 200 статусом вы получите 40x код и следующие 2 поля:
В поле error находится системный идентификатор ошибки, в error_description — описание ошибки на английском языке.
Возможные значения error:
Переданы не все необходимые параметры запроса или значение code не был найден в базе выданных кодов.
Данная ошибка сигнализирует о том, что вы попытались произвести авторизацию по неизвестному для нашего OAuth2 сервера типу Grant.
Ошибки при запросе информации о пользователе¶
Ответ со статусом 401 указывает на то, что заголовок Authorization не присутствует в запросе или его значение сформировано неверно. Тело ответа будет следующим:
Ответ со статусом 403 сигнализирует о том, что переданный в заголовке Authorization токен не содержит scope account_info или он истёк. Получаемый ответ будет иметь следующий формат:
Ошибки при обновлении токена доступа¶
При выполнении обновления токена доступа вам могут встретиться те же ошибки, что и при обмене кода на ключ доступа, а также несколько новых:
Переданы не все необходимые параметры запроса или значение refresh_token не был найден в базе выданных токенов.
Были перечислены неподдерживаемые scope или запрошено больше, чем было у изначального токена.
1) Зайдите в Google Developers Console и создайте новый проект.
3) В панели управления включите API и сервисы, которые вы планируете использовать.
2. Пример получения токена (access token) для доступа к API Google на PHP
Устанавливаем библиотеку для работы с API Google на PHP:
composer require google/apiclient:"^2.0"
В данном курсе представлены базовые понятия о приложениях для коробочной и облачной версий Битрикс24, подробно рассмотрен процесс разработки локальных и тиражных приложений, а также даны общие рекомендации для разработчиков готовых решений и интеграций.
Начальные требования к подготовке
Для успешного изучения курса и овладения мастерством работы с собственными приложениями для Битрикс24 необходимо владеть (хотя бы на начальном уровне):
- основами PHP;
- основами HTML, CSS;
- опытом работы с API и REST API.
Важно! Для удобства пользователей ваших сервисов рекомендуется при создании приложений использовать однотипное оформление, близкое к стандартным интерфейсам.
Курс учебный, контрольные тесты и сертификация по нему не предусмотрены.
Баллы опыта
В конце каждого урока есть кнопка Прочитано! . При клике на неё в Вашу итоговую таблицу опыта добавляется то количество баллов, которое указано в прочитанном После нажатия кнопки Прочитано! появится
окно подтверждения:
уроке.
Периодически мы заново оцениваем сложность уроков, увеличивая/уменьшая число баллов, поэтому итоговое количество набранных Вами баллов может отличаться от максимально возможного. Не переживайте! Отличный результат - это если общее число набранных Вами баллов отличается от максимального на 1-2%.
Существует специальный портал для разработчиков приложений. На нём вы можете задать вопросы более опытным разработчикам, обсудить нюансы и тонкости работы технологии REST.
Если вы нашли неточность в тексте, непонятное объяснение, пожалуйста, сообщите нам об этом в комментариях.
Читайте также: