1 (изменено: Malcev, 2019-02-12 21:48:30)

Тема: AHK: Google OAuth 2.0 и YouTube API

Так как Гугл прекратил поддержку авторизации с броузеров без включенного джаваскрипт,
https://security.googleblog.com/2018/10 … ts-to.html
то автоматизировать, например, ютуб стало возможным только через апи.
Данный код не является полностью рабочим - не рассматривает возможные ошибки, не запрашивает обновление токена и т.д., так как автоматизировать ютуб у меня нужды нет, а просто так копаться в мануале лень.
Алгоритм:
Прежде всего нам надо зарегестрировать свое устройство.
Заходим в https://console.developers.google.com
Создаем новый проект.
Выбираем созданный проект.
Переходим на вкладку Dahboard, нажимаем Enable Apis and Services.
Находим YouTube Data API v3, нажимаем на него, потом нажимаем на Enable.
Нажимаем на Create Credentials справа-> Api Key
Нажимаем на API key в фразе: "If you wish you can skip this step and create an API key, client ID, or service account".
Нажимаем Create.
Тем самым получаем API ключ для ютуба типа такого: "AIzaS9999999999999nm4rYaTA3EC397_ik"
Нажимаем на OAuth Consent Screen, в Application name вписываем любое имя, нажимаем save.
Нажимаем Create Credentials -> OAuth Client ID -> Other -> Create
Скачиваем JSon.
Должен скачаться такой:

{"installed":{"client_id":"341870872-dgbbg66.apps.googleusercontent.com","project_id":"certain-hau-29","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"JJN1OS7110v-j","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}

В нем нам нужны client_id и client_secret.
Теперь нам надо разрешить доступ нашего устройства.
Создаем такой код со своими данными:

; изменяем данные
ClientId := "341870872-dgbbg66.apps.googleusercontent.com"
ClientSecret := "JJN1OS7110v-j"

; дальше не изменяем
RedirectUri := "http://localhost"
scope := "https://www.googleapis.com/auth/youtube"
msgbox % clipboard := "https://accounts.google.com/o/oauth2/auth?redirect_uri=" UriEncode(RedirectUri) "&response_type=code&client_id=" ClientId "&scope=" UriEncode(scope) "&clientSecret=" ClientSecret "&approval_prompt=force"

UriEncode(Uri)
{
   VarSetCapacity(Var, StrPut(Uri, "UTF-8"), 0)
   StrPut(Uri, &Var, "UTF-8")
   f := A_FormatInteger
   SetFormat, IntegerFast, H
   While Code := NumGet(Var, A_Index - 1, "UChar")
      If (Code >= 0x30 && Code <= 0x39 ; 0-9
         || Code >= 0x41 && Code <= 0x5A ; A-Z
         || Code >= 0x61 && Code <= 0x7A) ; a-z
         Res .= Chr(Code)
      Else
         Res .= "%" . SubStr(Code + 0x100, -1)
   SetFormat, IntegerFast, %f%
   Return, Res
}

Запускаем его, полученную ссылку вставляем в браузер, переходим по ней.
Разрешаем использовать наше устройство и в итоге будет перенаправление на 404 страницу.
Копируем из адресной строки часть http://localhost/?code=4/7wCaeBV61IBslGg5pU9AZZ-XvrtJp7Dmnfh_khOlv6Co-sUuL0OMd7jt5s&scope.
Это код авторизации.
После чего создаем и запускаем следующий скрипт:

; изменяем данные
ClientId := "341870872-dgbbg66.apps.googleusercontent.com"
ClientSecret := "JJN1OS7110v-j"
AuthorizationCode := "4/7wCaeBV61IBslGg5pU9AZZ-XvrtJp7Dmnfh_khOlv6Co-sUuL0OMd7jt5s"

; дальше не изменяем
RedirectUri := "http://localhost"
Request := "grant_type=authorization_code&code=" AuthorizationCode "&redirect_uri=" UriEncode(RedirectUri) "&client_id=" ClientId "&client_secret=" ClientSecret
WinHTTP := ComObjCreate("WinHTTP.WinHTTPRequest.5.1")
WinHTTP.Open("POST", "https://accounts.google.com/o/oauth2/token", true)
WinHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
WinHTTP.Send(Request)
WinHTTP.WaitForResponse()
msgbox % clipboard := WinHTTP.ResponseText

UriEncode(Uri)
{
   VarSetCapacity(Var, StrPut(Uri, "UTF-8"), 0)
   StrPut(Uri, &Var, "UTF-8")
   f := A_FormatInteger
   SetFormat, IntegerFast, H
   While Code := NumGet(Var, A_Index - 1, "UChar")
      If (Code >= 0x30 && Code <= 0x39 ; 0-9
         || Code >= 0x41 && Code <= 0x5A ; A-Z
         || Code >= 0x61 && Code <= 0x7A) ; a-z
         Res .= Chr(Code)
      Else
         Res .= "%" . SubStr(Code + 0x100, -1)
   SetFormat, IntegerFast, %f%
   Return, Res
}

Ответ должен прийти c access_token и refresh_token:

{
  "access_token": "ya29.GluuBhDBPs66aSxf3TR0k7VetBWezYD_GXBcyKIBMIIOjWkkfsPcNDDh4pVCXy5U4C-g3Y1GxxF_26",
  "expires_in": 3600,
  "refresh_token": "1/SjYrJK9Ja2N57TxxIdoxvMTrrj2vDReeFK7yMOTLgA6fLsJp",
  "scope": "https://www.googleapis.com/auth/youtube",
  "token_type": "Bearer"
}

После чего можно подключиться к управлению апи ютуба.
Следующий код добавляет видео в плейлист:

; изменяем данные
videoId := "A_QfO7g1YsI"
playlistId := "PLp9-Tn608wZdTS44vpp9hYhke"
YoutubeApiKey := "AIzaS9999999999999nm4rYaTA3EC397_ik"
access_token := "ya29.GluuBhDBPs66aSxf3TR0k7VetBWezYD_GXBcyKIBMIIOjWkkfsPcNDDh4pVCXy5U4C-g3Y1GxxF_26"
refresh_token := "1/SjYrJK9Ja2N57TxxIdoxvMTrrj2vDReeFK7yMOTLgA6fLsJp"

; дальше не изменяем
url := "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&key=" YoutubeApiKey
Json = {'snippet': {'playlistId': '%playlistId%', 'resourceId': {'kind': 'youtube#video', 'videoId': '%videoId%'}}}

WinHTTP := ComObjCreate("WinHTTP.WinHTTPRequest.5.1")
WinHTTP.Open("POST", url, true)
WinHTTP.SetRequestHeader("Authorization", "Bearer " access_token)
WinHTTP.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko")
WinHTTP.SetRequestHeader("Content-Type", "application/json")
WinHTTP.Send(Json)
WinHTTP.WaitForResponse()
msgbox % WinHTTP.ResponseText
+ DD

2

Re: AHK: Google OAuth 2.0 и YouTube API

Обновлять токен так:

; изменяем данные
ClientId := "341870872-dgbbg66.apps.googleusercontent.com"
ClientSecret := "JJN1OS7110v-j"
RefreshToken := "1/SjYrJK9Ja2N57TxxIdoxvMTrrj2vDReeFK7yMOTLgA6fLsJp"

; дальше не изменяем
Request := "refresh_token=" RefreshToken "&client_id=" ClientId "&client_secret=" ClientSecret "&grant_type=refresh_token"
WinHTTP := ComObjCreate("WinHTTP.WinHTTPRequest.5.1")
WinHTTP.Open("POST", "https://accounts.google.com/o/oauth2/token", true)
WinHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
WinHTTP.Send(Request)
WinHTTP.WaitForResponse()
msgbox % clipboard := WinHTTP.ResponseText

3 (изменено: svoboden, 2020-01-07 17:32:42)

Re: AHK: Google OAuth 2.0 и YouTube API

Так нет параметра:

access_type=offline

Токен обновления не придет.

4 (изменено: Malcev, 2020-01-07 17:51:33)

Re: AHK: Google OAuth 2.0 и YouTube API

Первый и последний раз я пробовал обновлять токен год назад, когда и написал тот пост.
Тогда у меня приходил.
Возможно в каких-то случаях и не приходит - я не углублялся.

5 (изменено: svoboden, 2020-01-09 22:24:46)

Re: AHK: Google OAuth 2.0 и YouTube API

Просто там прям в справке написано, что:

Note that the refresh token is only returned if your application set the access_type parameter to offline in the initial request to Google's authorization server.

Вот так придет токен обновления:

ClientId := "341870872-dgbbg66.apps.googleusercontent.com"
ClientSecret := "JJN1OS7110v-j"

RedirectUri := "http://localhost"
scope := "https://www.googleapis.com/auth/youtube"
msgbox % clipboard := "https://accounts.google.com/o/oauth2/auth?redirect_uri=" UriEncode(RedirectUri) "&response_type=code&client_id=" ClientId "&scope=" UriEncode(scope) "&access_type=offline" "&include_granted_scopes=true" "&state=state_parameter_passthrough_value" "&clientSecret=" ClientSecret "&approval_prompt=force"

UriEncode(Uri)
{
   VarSetCapacity(Var, StrPut(Uri, "UTF-8"), 0)
   StrPut(Uri, &Var, "UTF-8")
   f := A_FormatInteger
   SetFormat, IntegerFast, H
   While Code := NumGet(Var, A_Index - 1, "UChar")
      If (Code >= 0x30 && Code <= 0x39 ; 0-9
         || Code >= 0x41 && Code <= 0x5A ; A-Z
         || Code >= 0x61 && Code <= 0x7A) ; a-z
         Res .= Chr(Code)
      Else
         Res .= "%" . SubStr(Code + 0x100, -1)
   SetFormat, IntegerFast, %f%
   Return, Res
}

6

Re: AHK: Google OAuth 2.0 и YouTube API

А зачем вам нужен новый refresh token?
Он же постоянный. По вашей ссылке:

Refresh tokens are valid until the user revokes access

Мой же код из 2 поста получает новый access_token.

7

Re: AHK: Google OAuth 2.0 и YouTube API

Ну да, токен обновления приходит только раз, потом нужно снова регистрировать приложение. Немного не понял, так без параметра:

access_type=offline

токен обновления вообще не придет.

8

Re: AHK: Google OAuth 2.0 и YouTube API

Я не понимаю, что именно вы не понимаете.
В первом сообщении написано, как получить Access Token и Refresh Token.
Во втором, как получить новый Access Token.
Только что проверил - всё работает.

9 (изменено: svoboden, 2020-01-09 22:26:07)

Re: AHK: Google OAuth 2.0 и YouTube API

Ну у меня не приходит Refresh Token без параметра access_type=offline.

10

Re: AHK: Google OAuth 2.0 и YouTube API

А аы делали по алгоритму из первого поста?

11 (изменено: svoboden, 2020-01-09 23:01:09)

Re: AHK: Google OAuth 2.0 и YouTube API

Да, я же поэтому и пишу, что не пришел токен обновления по инструкции.

12

Re: AHK: Google OAuth 2.0 и YouTube API

А какой приходит ответ?

; изменяем данные
ClientId := "341870872-dgbbg66.apps.googleusercontent.com"
ClientSecret := "JJN1OS7110v-j"
AuthorizationCode := "4/7wCaeBV61IBslGg5pU9AZZ-XvrtJp7Dmnfh_khOlv6Co-sUuL0OMd7jt5s"

; дальше не изменяем
RedirectUri := "http://localhost"
Request := "grant_type=authorization_code&code=" AuthorizationCode "&redirect_uri=" UriEncode(RedirectUri) "&client_id=" ClientId "&client_secret=" ClientSecret
WinHTTP := ComObjCreate("WinHTTP.WinHTTPRequest.5.1")
WinHTTP.Open("POST", "https://accounts.google.com/o/oauth2/token", true)
WinHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
WinHTTP.Send(Request)
WinHTTP.WaitForResponse()
msgbox % clipboard := WinHTTP.ResponseText

UriEncode(Uri)
{
   VarSetCapacity(Var, StrPut(Uri, "UTF-8"), 0)
   StrPut(Uri, &Var, "UTF-8")
   f := A_FormatInteger
   SetFormat, IntegerFast, H
   While Code := NumGet(Var, A_Index - 1, "UChar")
      If (Code >= 0x30 && Code <= 0x39 ; 0-9
         || Code >= 0x41 && Code <= 0x5A ; A-Z
         || Code >= 0x61 && Code <= 0x7A) ; a-z
         Res .= Chr(Code)
      Else
         Res .= "%" . SubStr(Code + 0x100, -1)
   SetFormat, IntegerFast, %f%
   Return, Res
}

13

Re: AHK: Google OAuth 2.0 и YouTube API

Примерно такой:

{
  "access_token": "ya29.Il-4Bw5mszyLdRC5UXoj4eleUrY5GyZCwaXlJgq_p_TdolJQervhDkeSfdkWd7Q-uvhiUipScnR5uxFhwf9aIzHqFHCdty5rTvBj4Yp54LO0ESyQ2SiNY7t05VxF097O5Q",
  "expires_in": 3600,
  "scope": "https://www.googleapis.com/auth/youtube",
  "token_type": "Bearer"
}

14

Re: AHK: Google OAuth 2.0 и YouTube API

Не знаю почему у вас не приходит.
Должен приходить.
https://developers.google.com/android-p … horization