В этом уроке вы узнаете:
- Как получить OAuth-токен вручную
- Почему OAuth-токен может перестать действовать
- Что дальше
- Полезные ссылки
- Вопросы
В этом уроке мы подробнее расскажем об OAuth-токенах, их получении и использовании.
Из предыдущих уроков вы уже знаете, что API Директа использует OAuth-авторизацию. Напомним, что в каждом запросе к API необходимо указывать OAuth-токен. В токене зашифрована информация как о приложении, так и о пользователе. Токен используется для того, чтобы определить: от имени какого пользователя Директа приложение выполняет запрос; действительно ли пользователь разрешил этому приложению доступ к своим данным в Директе; есть ли у самого пользователя нужные полномочия для работы с теми рекламными материалами, к которым он обращается.
Таким образом, при работе с Директом через API нет необходимости передавать пароль от аккаунта пользователя. Достаточно передать OAuth-токен, что делает процесс работы с API Директа более безопасным. Но важно понимать, что для каждого пользователя в приложении требуется получить отдельный токен.
На начальных этапах разработки приложения достаточно вручную получить так называемый отладочный токен. В дальнейшем, при переходе к реальной работе, необходимо будет реализовать в приложении удобный для пользователей механизм получения токена, когда пользователь просто нажимает кнопку Разрешить в веб-интерфейсе Яндекс.OAuth, а затем Яндекс.OAuth передает приложению токен в автоматическом режиме.
Обратите внимание, что токен, полученный вручную, ничем не отличается от полученного в автоматическом режиме. Токен дает возможность управлять реальными рекламными материалами пользователя, независимо от способа, которым этот токен получен.
В одном из предыдущих уроков вы зарегистрировали приложение на Яндекс.OAuth, при этом в поле Callback URI #1 подставили URL для разработки. Если вы этого не сделали — оставили поле незаполненным или указали другое значение, перейдите на Яндекс.OAuth (https://oauth.yandex.ru) и отредактируйте настройки приложения: установите флажок Веб-сервисы, нажмите ссылку Подставить URL для разработки и сохраните изменения. Теперь вы можете вручную получить токен для тестового пользователя.
В роли тестового пользователя вы можете использовать тот же аккаунт разработчика, под которым вы зарегистрировали приложение и подали заявку на доступ. В данном курсе мы рассматриваем именно этот вариант.
Для получения токена вручную выполните следующие действия:
-
Войдите на Яндекс под своим логином.
-
Перейдите по ссылке
https://oauth.yandex.ru/authorize?response_type=token&client_id=ИДЕНТИФИКАТОР_ПРИЛОЖЕНИЯ
(вместо ИДЕНТИФИКАТОР_ПРИЛОЖЕНИЯ укажите идентификатор своего приложения).
-
На открывшейся странице нажмите кнопку Разрешить.
-
Яндекс.OAuth перенаправит вас на страницу, на которой отобразит токен. Токен будет также добавлен в адресную строку. Скопируйте токен, чтобы использовать его в запросах к API.
Внимание.
-
Никому не сообщайте токен — с его помощью можно получить доступ к данным пользователя в Директе.
-
Вы можете создать отдельный аккаунт тестового пользователя (или несколько аккаунтов). Для нового пользователя необходимо создать аккаунт в веб-интерфейсе Директа, выбрав страну и валюту расчетов, а также принять пользовательское соглашение в разделе API. Чтобы получить токен для пользователя, нужно войти на Яндекс под его логином и повторить описанную выше процедуру.
Совет. Если вам не удалось получить токен по какой-либо причине, воспользуйтесь подробной инструкцией.
Со временем токен может стать недействительным и потребуется получить новый.
Все токены пользователя будут отозваны, если:
-
пользователь изменил пароль на Яндексе;
-
пользователь нажал ссылку Выйти на всех компьютерах.
Токен, выданный для определенного приложения, будет отозван, если:
-
пользователь отменил доступ приложения к своим данным (эта возможность доступна в веб-интерфейсе Яндекс Паспорта);
-
разработчик приложения изменил права доступа для своего приложения;
-
срок жизни токена истек.
Полный перечень ситуаций, при которых Яндекс.OAuth отзывает токены, приведен в документации Яндекс.OAuth.
Итак, вы получили токен, с которым можете выполнять запросы к API. Впереди последний подготовительный этап: создание и настройка Песочницы — тестовой среды для отладки приложения. Затем мы перейдем непосредственно к составлению запросов к API.
Документация Яндекс.OAuth:
-
Чем отладочный токен отличается от полученного в автоматическом режиме?
Он дает доступ только к тестовой среде.Он выдается на одну неделю, после чего нужно получать новый токен.Отличается только способом получения, оба токена предоставляют одинаковые возможности.
Неверно.
Неверно.
Верно!
-
Может ли токен пользователя перестать действовать?
Нет, токен выдается навсегда.Да, может, например если пользователь сменил пароль от аккаунта или нажал кнопку Выйти на всех компьютерах.Нет, не может, пока пользователь сам не захочет поменять токен.
Неверно.
Верно!
Неверно.
-
Какие условия необходимы для получения отладочного токена?
Вы знаете идентификатор и пароль приложения.Подана заявка на тестовый доступ, и вы знаете идентификатор приложения.Войти на Яндекс под тем логином, для которого необходимо получить токен, и знать идентификатор приложения.Подана заявка на тестовый доступ, и вы авторизованы на Яндексе под тем логином, для которого необходимо получить токен.
Неверно.
Неверно.
Верно!
Неверно.
Уровень сложности
Простой
Время на прочтение
6 мин
Количество просмотров 301
На тему OAuth 2.0 написано море хороших статей (например: 1,2), переписывать их не буду, а лучше расскажу про изобретение велосипеда то, как я пытался на практике реализовать авторизацию в Google Api посредством простых запросов.
Про существование библиотек Sign-In, AppAuth, AccountManager я в курсе, но чего они все не дают, так это четкого понимания как происходит обмен ключами и что они из себя представляют. Было принято решение получить токены от Google Books без применения специализированных библиотек для того,чтобы разобраться как все устроено, возможно кому-то пригодится. Сразу скажу, что не являюсь экспертом, и крутым разработчикам будет не интересно изобретение велосипедов,но возможно кому-то из начинающих разработчиков пригодится данная информация.
В теоретические выкладки и перерисовывание схем из других постов вдаваться не буду, оставлю ссылки на основные источники:
-
OAuth 2.0 for Mobile & Desktop Apps – инстркукция от Google
-
The OAuth 2.0 Authorization Framework – текст стандарта RFC6749 – здесь описан сам протокол OAuth
-
Proof Key for Code Exchange by OAuth Public Clients текст стандарта RFC7636 – PKCE стандарт для ключей (токенов)
Если кратко, то алгоритм авторизации выглядит следующим образом:
-
Настроить проект в консоли, добыть Client ID
-
Сформировать строку code_verifier
-
Сформировать строку code_challenge
-
Собрать ссылку для авторизации и открыть по ней экран авторизации
-
Получить code
-
Обменять code на токены: access_token и update_token
-
Решить вопрос с хранением токенов.
Получение Client ID
Подготовительная часть (подробная инстукция от Google здесь):
-
Перейти в Google Developer Console и создать проект.
-
Перейти в OAuth consent screen – создать экран авторизации:
Для обычного приложения нужно выбрать тип External. -
После заполнения формы необходимо добавить Scopes необходимые вам области доступа – можно выбрать отсюда, в моей случае scope для доступа к книгам пользователя это строка, которая выглядит как ссылка “https://www.googleapis.com/auth/books”.
-
Далее нужно добавить тестовых пользователей – реальные аккаунты, с которых вы будете тестировать приложение. Пока статус приложения “Testing” – будут допускаться только пользователи из списка тестовых.
-
Переходим в Credentials – необходимо создать OAuth client ID -> тип приложения Android -> Здесь понадобится ввести имя пакета – package name, оно должно совпадать с настройками в Gradle applicationId:
defaultConfig {
applicationId "ru.example.googlebooksclient"
Также потребуется ввести SHA-1 certificate fingerprint (подробнее про App Signing). Для отладки приложения можно взять debug key – добыть его можно в терминале (стандартный пароль для получения ключа – android), нужно скопировать SHA1 и закинуть в форму. Типичный путь для Android Studio:
keytool -list -v -keystore ~/.android/debug.keystore
Certificate fingerprints:
SHA1: D9:E9:59:FA:7A:46:72:4E:60:1F:96:28:8C:F9:AE:82:3A:5D:2F:03
После того как форма заполнена, будет виден заветный Client ID. Остается зайти в API LIbrary, выбрать нужный API и активировать.
Ну и, конечно, добавить в манифест разрешение на использование интернета.На этом подготовка окончена.
<uses-permission android:name="android.permission.INTERNET" />
Коды verifier и challenge
Теперь, когда есть Client ID, можно переходить к самим запросам.
code_verifier-
криптографически-устойчивая случайная строка длиной от 43 до 128 символов. Читаем стандарт – рекомендуется генерировать строку длиной 32 байта и пропустить ее через base64url-encode, что на выходе даст 43 символа. Тут я наступил на грабли и пытался использовать обычный base64-encode, который на пару символов отличается, но этого достаточно чтобы ничего не работало. Генерируем code_verifier:
val charPool : List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
val secureRandom = SecureRandom()
val str= (1..STRING_LENGTH).map {
secureRandom.nextInt(charPool.size).let { charPool[it] }
}.joinToString("")
codeVerifier= Base64.getUrlEncoder().withoutPadding()
.encodeToString(str.toByteArray())
Должна получиться строка длинной 43 символов вида:
U0tTVUFNWВJZQUJpV3ZNOGszZ2FscFgxT0xUcVo3a2M
code_challenge – читаем стандарт, данная строка получается из прошлой с помощью BASE64URL-ENCODE(SHA256(ASCII(code_verifier))), сказано -сделано:
val md=c.getInstance("SHA-256")
codeChallenge= Base64.getUrlEncoder().withoutPadding()
.encodeToString(md.digest(codeVerifier.toByteArray()))
Получится строка, похожая на первую,тоже 43 символа. Теперь все готово для того,чтобы отправить пользователя на экран подтверждения наших полномочий.
Экран авторизации
Согласно шагу 2 инструкции собираем ссылку для перехода на экран авторизации:
https://accounts.google.com/o/oauth2/v2/auth
Необходимо добавить параметры:
-
client_id – наш client id из консонли
-
redirect_uri – ссылка для обратного перехода в приложение после авторизации, причем в документации сказано, что она должна точно совпадать с ссылкой которую мы указали в настройках проекта, тут не совсем ясно, мы же ничего не указывали, кроме имени пакета, ок – ссылкой будет applicationId -имя пакета
-
response_type – для android приложений должно быть “code”
-
scope – выбранный ранее Scope
-
code_challenge – строка code_challenge
-
code_challenge_method – для SHA256 должно быть “S256”
Собираем ссылку:
https://accounts.google.com/o/oauth2/v2/auth
?client_id=189284811864-i5gehoqcvqesloriuccem7iu2p3hlare.apps.googleusercontent.com
&redirect_uri=ru.example.googlebooksclient:/
&scope=https://www.googleapis.com/auth/books
&code_challenge=VR2MxXBNS71bE6RudDxCQ3M3-cc72B7ph_S1jOmZu48
&code_challenge_method=S256
&response_type=code
И тут меня ожидали грабли: redirect_uri считается некорректной, пока не добавим к applicationId в конце “:/”, но это мелочи, теперь нужно перейти по ссылке:
// добавляем зависимость в Gradle
implementation 'androidx.browser:browser:1.5.0'
//открыть ссылку
val authUrl="$authlink?client_id=$MY_CLIENT_ID&redirect_uri=$MY_REDIRECT_URI:/" +
"&scope=$BOOKS_SCOPE&code_challenge=$codeChallenge&code_challenge_method=S256&response_type=code"
val builder = CustomTabsIntent.Builder( )
builder.setShowTitle(true)
builder.setInstantAppsEnabled(true)
val customBuilder = builder.build()
customBuilder.launchUrl(curContext, Uri.parse(authUrl))
И прилетает ошибка disallowed_useragent – так я узнал, что использование WebView запрещено в целях безопасности.
Web developers may encounter this error when an Android app opens a general web link in an embedded user-agent and a user navigates to Google’s OAuth 2.0 authorization endpoint from your site. Developers should allow general links to open in the default link handler of the operating system, which includes both Android App Links handlers or the default browser app. The Android Custom Tabs library is also a supported option.
Так как тестировал все в эмуляторе, нормальный браузер отсутствовал, проверил на устройствах – работает, значит ставим Google Chrome в эмулятор и двигаемся дальше.
Обмен кода авторизации на токены
После того, как пользователь войдет в аккаунт, он будет переадресован обратно в приложение. Для того, чтобы приложение открылось по ссылке – необходимо добавить intent-filter в манифест:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="ru.example.googlebooksclient"/>
</intent-filter>
Для того чтобы Activity не перезапускалась каждый раз заново в манифест(в activity) нужно добавить:
android:launchMode="singleTask"
В таком случае, при обращении к уже существующей Activity, она не будет создаваться заново, а будет вызван метод onNewIntent(intent: Intent).Поле intent.data будет содержать непосредственно ответ. Ответ может содержать code в случае успеха, или error если, например, пользователь отказался войти в аккаунт.
code=4%2F0AbUR1VPxw9shy7AwPM7XTnrK_1Ejble9dwd7oe3GexdLho_1D-jhT5RSets8z-q1e6RaoA
Теперь когда есть code – осталось обменять его на заветные токены. Для этого необходимо отправить POST запрос на
https://oauth2.googleapis.com/token
с параметрами:
client_id – наш client_id
code – полученный код
code_verifier – строка code_verifier
grant_type=authorization_code
redirect_uri =наш redirect_uri
В ответ на POST запрос прилетит JSON:
{
"access_token": "ya25.a0AWY6Ckkl292RjoOMfhEtX8Ub_UPM-P3WHQSD1v5QSU_zfr5ig4KB_yMjXmmeIQXg8gRt4hmooGe2OyRFtLOxU2UHYvj40v9JS4kmhGhE2S3lIN5NxcWnOLJOqX9OhpZTzKVi9kofm9LwzFAXKY7B49wKMpiraCgYKARwSARISFQG1tDrpIMvYW4ruiJUUDUvQjlEapw0163",
"expires_in": 3599,
"refresh_token": "1//0c1f5N617z5JyCgYIARAAGAwSNwF-L9IrQnmw_Xx670pofbNnUtH5alJTHYoheRisu35RH_PWJzgIaQW6PdlRrxdzmJTEPnw9eCo",
"scope": "https://www.googleapis.com/auth/books",
"token_type": "Bearer"
}
Остается решить вопрос только с хранением и обновлением токенов, хранить токены локально – в любом случае небезопасно, можно придумать какое-то шифрование и хранить их SharedPreferences. Время действия токена в секундах указано в expires_in.
Обновление токена
Для обновления токена, необходимо отправить POST запрос на:
https://oauth2.googleapis.com/token
с параметрами: client_id, refresh_token, grant_type=refresh_token
В ответ прилетит GSON с новым access_token и временем действия.
Отмена авторизации
Для отмены авторизации достаточно отправить POST запрос для отмены действия токена:
https://oauth2.googleapis.com/revoke?token={здесь токен}
Итог
В итоге получилось приложение с одной Activity, которое с помощью Custom Tabs открывает экран авторизации в Google, получает токены доступа. При этом никак не привязано к аккаунтам в телефоне, которых может и не быть. Очевидно что вариант черновой, но дает понимание алгоритма действий и в случае необходимости, данный алгоритм можно допилить под нестандартные API или применить знания при допиливании “костылей” к существующим библиотекам.
Ссылка на Github – приложение закидывает все запросы и ответы в Logcat.
In this lesson, you will learn:
- How to get an OAuth token manually
- Why can the OAuth token stop working
- What’s next
- Useful links
- Questions
In this lesson, you will learn more about OAuth tokens, how to get them and use them.
From the previous lessons, you already know that Yandex Direct API uses OAuth authorization. Remember that you must specify your OAuth token in every API request. The token encrypts information both about the app and user. The token is used in order to determine, on behalf of which Yandex Direct user the app executes the query; whether the user has authorized the app to access their data in Yandex Direct; whether the user is authorized to access the requested ads.
Hence, when accessing Yandex Direct via the API, you do not need to pass the user account password. It is sufficient to pass the OAuth token: it makes the interaction with the Yandex Direct API more secure. However, it is important to keep in mind that you need to get a separate token for each user of your app.
At the initial stages of app development, you only need to manually obtain a so-called debugging token. Afterwards, when you roll out your app into production, you should implement a user-friendly way to get a token from within the app just on button click: the user clicks Allow in the Yandex OAuth web interface, and then Yandex OAuth returns the token to the app automatically.
Please note that the manually obtained token is in no way different from the automatically obtained one. With the token you can manage the user’s real advertising materials, regardless of how the token was obtained.
In a previous lesson, you registered your app on Yandex OAuth, putting the development URL in the Callback URI #1 field. If you did not do this (i.e., left the field blank or set a different value, go to Yandex OAuth (https://oauth.yandex.com) and edit app settings: select the Web services checkbox, click the Set URL for development link, and save the changes. Now you can manually get a token for the test user.
As a test user, you can use the same developer account you have used to register your app and apply for access. We are focusing on this very option in this course.
To get a token manually, follow these steps:
-
Log in to Yandex with your username.
-
Follow link
https://oauth.yandex.com/authorize?response_type=token&client_id=APP_IDENTIFIER
(put your app identifier instead of APP_ID).
-
On the page that opens, click Allow.
-
Yandex OAuth redirects you to the page displaying the token. The token is also added to the URL shown in the address bar. Copy the token to use it in your API requests.
Attention.
-
Do not share the token with anyone: one can use it to access the user’s data in Yandex Direct.
-
You can create a separate test user account (or multiple accounts). For a new user, you must create an account in the Yandex Direct web interface, having selected the country and payment currency, and accepted the user agreement in the API section. To get a token for the user, log in to Yandex using their username and repeat the above procedure.
Tip. If you were not able to get a token for some reason, use the detailed instruction.
The token may expire over time, so you may need to get a new one.
All the user’s tokens are revoked if:
-
the user has changed their Yandex password
-
the user clicked the Log out of all computers link.
A token issued for a specific app is revoked if:
-
the user revoked the app access to their data (this feature is available in the Yandex Passport web interface)
-
the app developer changed the access rights for their app
-
the token has expired.
For the full list of situations when Yandex OAuth revokes tokens, see the Yandex OAuth documentation.
So you have received a token you can use to make the API requests. The last preparation stage is ahead: create and configure Sandbox, a test environment for app debugging. Then we will proceed directly to making API requests.
Yandex OAuth documentation:
-
What is the difference between a debugging token and a token obtained automatically?
It only gives access to the test environment.It is issued for one week, after which you need to get a new token.It differs only in the way it is received; both tokens provide the same features.
False.
False.
True.
-
Can the user’s token stop working?
No, the token is issued indefinitely.Yes, it can stop working, for example, if the user changed the account password or clicked Log out of all computers.No, it can not expire before the user decides to change the token.
False.
True.
False.
-
What conditions have to be met to obtain a debugging token?
You know the app ID and app password.You have submitted a request for trial access and you know the app ID.You logged in on Yandex with the username you have requested a token for, and you know your app ID.You have requested trial access and you are logged in on Yandex with the username you need to get a token for.
False.
False.
True.
False.
I am new to OAuth 2.0 and I wish to know what is the best practice / location to store access token and refresh token in generic e-commerce web site.
Question 1:
Where should access token and refresh token be stored in web sites? (cookies, web storage or local storage). And where big companies like google, dropbox store the access token and refresh token?
Question 2:
If refresh token is stored on the client side (taking browser in desktop/laptop), isn’t it possible that someone has physical gain on that device able to get the refresh token and device information and use it to generate access token on other place?
Question 3:
I have see some post that suggest that refresh token should never be stored and known by client side. Then, where should refresh token be stored and how to reauthenticate in this case?
asked Sep 17, 2015 at 0:10
A1 — you must store refresh token in http-cookie (which is not accessible by js) and database both and validate cookie refresh token using database. Store access token in memory or session storage but it must expires in a short period of time
ANSWER 1, ANSWERS BOTH QUESTION 1 AND 3
answered Feb 18, 2022 at 7:12
A1: access token has a much shorter time-to-live than refresh token, you may store refresh token in local storage or even other secure storage on server side; for access token, both web storage and local storage are fine; storing access token in cookie does not make much sense
A2: yes, hence refresh token should not be stored on client side;
A3: stored it on server/service side
answered Mar 15, 2016 at 15:54
Токен не существует сам по себе, а выдается приложению от имени чьего-то аккаунта в Яндексе. Таким образом владелец аккаунта разрешает этому приложению доступ к определенным операциям со своим аккаунтом. Токен является реализацией такого разрешения.
1. Регистрируем приложение
Заполняем форму на https://oauth.yandex.ru/client/new. Обязательно сделать следующее:
- указать название приложения (например, “watches.ru site engine”)
- в разделе Callback URI нажать “Подставить URL для разработки”, в поле возникнет адрес от Яндекса
- среди доступов найти нужный раздел (например, для Яндекс.Маркета и Беру.ру это Яндекс.Маркет).
После отправки формы отобразится страница с параметрами приложения, отсюда нужно взять его идентификатор и пароль.
В дальнейшем доступ к этим данным осуществляется по адресу https://oauth.yandex.ru/client/<id приложения>
. Страница будет доступна только тому аккаунту, от имени которого было создано приложение (создать приложения без аккаунта в Яндексе нельзя).
2. Разрешаем приложению доступ – получаем токен
-
Заходим на Яндекс с учетной записью пользователя, к аккаунту которого приложение должно запросить доступ.
(Он может отличаться от аккаунта, из-под которого было создано приложение, но может и совпадать.) -
Взять идентификтор приложения, подставить его в адрес
https://oauth.yandex.ru/authorize?response_type=token&client_id=<идентификатор приложения>
и открыть страницу. Нажать Разрешить. -
Прямо на странице будет отображен новый токен. Его нужно куда-то сохранить, т.к. как его посмотреть потом – пока неизвестно.
А в адресе в параметре expires – время жизни в секундах (например, для приложения с доступом к Яндекс.Маркету это один год).
Эти процедуры подробно описаны здесь: https://tech.yandex.ru/oauth/doc/dg/tasks/get-oauth-token-docpage/
3. Отправляем токен с HTTP-запросами
В состав запросов токен включается с помощью заголовка Authorization: Oauth
, куда входит также идентификатор приложения:
Authorization: OAuth oauth_token="авторизационный_токен", oauth_client_id="идентификатор_приложения"
См. https://yandex.ru/dev/market/partner-marketplace-cd/doc/dg/concepts/authorization-docpage/