アクセストークンを更新しようとすると、エラーが発生します。
400不正な要求
{エラー:「unauthorized_client」}
GoogleトークンURIから:
{
"error" : "invalid_request"
}
私はこの回答 here と公式のGoogleドキュメント(POST
リクエストの外観を説明する)を読みましたが、違いはありません。
私のPOST
リクエストをキャプチャしました(秘密は削除されました):
POST /SHOWMERAWPOST HTTP/1.1
User-Agent: Google-HTTP-Java-Client/1.10.3-beta (gzip)
Pragma: no-cache
Host: requestb.in
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 175
Connection: keep-alive
Cache-Control: no-cache
Accept-Encoding: gzip
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
grant_type=refresh_token&refresh_token=******&client_id=*******.apps.googleusercontent.com&client_secret=******
リクエストを送信するJavaコード:
RefreshTokenRequest req = new RefreshTokenRequest(new NetHttpTransport(), new JacksonFactory(), new GenericUrl(
getSecrets().getDetails().getTokenUri()), REFRESH_TOKEN);
req.set("client_id", getSecrets().getDetails().getClientId());
req.set("client_secret", getSecrets().getDetails().getClientSecret());
TokenResponse response = req.execute();
何か問題はありますか?
OAuth2プレイグラウンドでアクセストークンと更新トークンを作成し、アプリにコピーしました。自動化とトークンの更新のために異なるクライアントを持つことはできません。
問題の説明
@MartinVが与えたヒントで、私は最終的にそれを修正することができました!彼の答えはそれを解決する方法をあまりよく説明しないので、私はそれをここに投稿します。
問題はすべて GoogleのOAuth Playground を使用して更新トークンを生成したためですが、最初のステップで[Authorize APIs]をクリックすると、プレイグラウンドアプリを使用して画面を集中してください。その後、作成するすべてのトークンはプレイグラウンドアプリでのみ使用できますが、もちろん、そのアプリのクライアントIDまたはクライアントシークレットのいずれかがわかりません。
[〜#〜]ソリューション[〜#〜]
解決策は、Playgroundが独自のクライアントIDとシークレットを使用するようにすることです。これを行うには、[設定]ボタンをクリックします。
クライアントIDとシークレットを入力します。ただし、その前に、そこに記載されているように、 開発者コンソール に移動して、OAuth 2.0クライアントIDクライアントを見つけ、編集して追加するhttps://developers.google.com/oauthplaygroundAuthorized redirect URIsの下。これを追加して変更を保存したら、プレイグラウンドに戻ってAPIの承認を試みます。私の場合、承認済みリダイレクトURIの変更が有効になるまで15分ほどかかりました。
完了したら、開発者コンソールからPlayground URIを削除することを忘れないでください!
[〜#〜]追加[〜#〜]
これを実行したら、Python=でこれを実行し、それが機能しました:
access_token = None
client_id = 'xxxxxxxx.apps.googleusercontent.com'
client_secret = 'xxxxxxxxxxxx'
refresh_token = 'xxxxxxxxxxxx'
token_expiry = None
token_uri = "https://accounts.google.com/o/oauth2/token"
user_agent = 'YourAgent/1.0'
credentials = client.GoogleCredentials(access_token, client_id, client_secret, refresh_token, token_expiry, token_uri, user_agent)
http = credentials.authorize(httplib2.Http())
credentials.refresh(http)
service = build('drive', 'v3', http=http)
req = service.files().list()
resp = req.execute(http=http)
私も同じ問題を抱えていました。解決策は、アプリケーションで認証するときとサーバーでトークンを更新するときに同じクライアントを使用することでした。
REST APIを使用してaccess_token
を取得し、それを使用してREST APIとやり取りする(たとえば、動画を非公開に追加するプレイリスト)refresh_token
を作成した後 上記 のように記述します。
import requests
import json
# according to https://stackoverflow.com/a/41556775/3774227
client_id = '<client_id>'
client_secret = '<client_secret>'
refresh_token = '<refresh_token>'
playlist_id = '<playlist>'
video_id = 'M7FIvfx5J10'
def get_access_token(client_id, client_secret, refresh_token):
url = 'https://www.googleapis.com/oauth2/v4/token'
data = {
'client_id': client_id,
'client_secret': client_secret,
'refresh_token': refresh_token,
'grant_type': 'refresh_token'
}
response = requests.post(
url=url,
data=data,
)
return response.json().get('access_token')
def add_video_to_playlist(playlist_id, video_id, access_token):
url = 'https://www.googleapis.com/youtube/v3/playlistItems'
params = {
'part': 'snippet',
}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer {}'.format(access_token)
}
data = {
'snippet': {
'playlistId': playlist_id,
'resourceId': {
'kind': 'youtube#video',
'videoId': video_id
},
}
}
requests.post(
url=url,
params=params,
headers=headers,
data=json.dumps(data)
)
if __name__ == '__main__':
access_token = get_access_token(client_id, client_secret, refresh_token)
add_video_to_playlist(playlist_id, video_id, access_token)