web-dev-qa-db-ja.com

アクセストークンを更新できません:応答は "unauthorized_client"です

アクセストークンを更新しようとすると、エラーが発生します。

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();

何か問題はありますか?

18
Martin V.

OAuth2プレイグラウンドでアクセストークンと更新トークンを作成し、アプリにコピーしました。自動化とトークンの更新のために異なるクライアントを持つことはできません。

11
Martin V.

問題の説明

@MartinVが与えたヒントで、私は最終的にそれを修正することができました!彼の答えはそれを解決する方法をあまりよく説明しないので、私はそれをここに投稿します。

問題はすべて GoogleのOAuth Playground を使用して更新トークンを生成したためですが、最初のステップで[Authorize APIs]をクリックすると、プレイグラウンドアプリを使用して画面を集中してください。その後、作成するすべてのトークンはプレイグラウンドアプリでのみ使用できますが、もちろん、そのアプリのクライアントIDまたはクライアントシークレットのいずれかがわかりません。

[〜#〜]ソリューション[〜#〜]

解決策は、Playgroundが独自のクライアントIDとシークレットを使用するようにすることです。これを行うには、[設定]ボタンをクリックします。

Playground settings

クライアント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)
23
Diego Jancic

私も同じ問題を抱えていました。解決策は、アプリケーションで認証するときとサーバーでトークンを更新するときに同じクライアントを使用することでした。

サーバー側のGoogle Calendar APIのアクセストークンを更新できません

0

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)
0
Livioso