web-dev-qa-db-ja.com

Gmail APIを使用してアクセストークンを取得する方法

このドキュメント に従って認証コードを取得しました。しかし、アクセストークンを取得しようとすると、常にエラーが発生しました。誰か助けてもらえますか?

public String AccessToken()
{
    String accessToken = "";
    StringBuilder strBuild = new StringBuilder();

    String authURL = "https://accounts.google.com/o/oauth2/token?";
    String code = "4/SVisuz_x*********************";
    String client_id = "******************e.apps.googleusercontent.com";
    String client_secret = "*******************";
    String redirect_uri = "urn:ietf:wg:oauth:2.0:oob";
    String grant_type="authorization_code";
    strBuild.append("code=").append(code)
            .append("&client_id=").append(client_id)
            .append("&client_secret=").append(client_secret)
            .append("&redirect_uri=").append(redirect_uri)
            .append("&grant_type=").append(grant_type);
    System.out.println(strBuild.toString());
    try{
        URL obj = new URL(authURL);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setDoOutput(true);
        con.setRequestMethod("POST");

        con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        con.setRequestProperty("Host", "www.googleapis.com");

        //BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(con.getOutputStream()));
        //bw.write(strBuild.toString());
        //bw.close();

        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(strBuild.toString());
        wr.flush();
        wr.close();

        //OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream());
        System.out.println(con.getResponseCode());
        System.out.println(con.getResponseMessage());             

    } catch (Exception e)
    {
        System.out.println("Error.");
    }
    return "";
}

このコードを実行すると、出力は400 Bad Request

13
tqjustc

Gmail APIを使用してアクセストークンを取得する方法

Ans:次のチュートリアル に従って、_OAuth 2.0_を使用しています。したがって、_OAuth 2.0_を使用してGoogle APIにアクセスするための基本的なパターンがあります。 4つの手順に従います。

  1. Google Developers ConsoleからOAuth 2.0認証情報を取得します。
  2. Google Authorization Serverからアクセストークンを取得します。
  3. アクセストークンをAPIに送信します。
  4. 必要に応じて、アクセストークンを更新します。

詳細については、チュートリアルに従うことができます OAuth 2.0を使用してGoogle APIにアクセスする

= Google Developers Console にアクセスして、OAuth 2.0の認証情報(_client ID_や_client secret_など)を取得して、Googleとあなたの申請


根本原因分析:

Issue-1:

コードを調査した後、欠けているものが見つかりました。コードがスムーズに実行される場合、コードは常に空の文字列を提供します。 AccessToken()メソッドは常に_return "";_を返すため

Issue-2:

_ catch (Exception e)
    {
        System.out.println("Error.");
    }
_

あなたのトライキャッチブロックは例外ブロックを行っています。なぜなら、コードを適切に完了していないようです。アクセストークンを準備するencodingを使用するだけでなく、JSONObjectもありません。だからそれは出力を与えています

エラー。

解決:

あなたのコードはこれと似ていると思いました tutorial

あなたのコードはあなたの問題を解決するためにさらなる変更を必要とするので。 LinkedHashMapまたはArrayListを使用することを提案します。それらは解決策を作るより簡単な方法を提供します。だからあなたの人生を楽にするために2つのサンプルコードを与えます。それらのいずれかを選択できます。 _refresh_token, client id, client secret and grant type_を自分のものに変更する必要があります。

_private String getAccessToken()
{
    try
    {
        Map<String,Object> params = new LinkedHashMap<>();
        params.put("grant_type","refresh_token");
        params.put("client_id",[YOUR CLIENT ID]);
        params.put("client_secret",[YOUR CLIENT SECRET]);
        params.put("refresh_token",[YOUR REFRESH TOKEN]);

        StringBuilder postData = new StringBuilder();
        for(Map.Entry<String,Object> param : params.entrySet())
        {
            if(postData.length() != 0)
            {
                postData.append('&');
            }
            postData.append(URLEncoder.encode(param.getKey(),"UTF-8"));
            postData.append('=');
            postData.append(URLEncoder.encode(String.valueOf(param.getValue()),"UTF-8"));
        }
        byte[] postDataBytes = postData.toString().getBytes("UTF-8");

        URL url = new URL("https://accounts.google.com/o/oauth2/token");
        HttpURLConnection con = (HttpURLConnection)url.openConnection();
        con.setDoOutput(true);
        con.setUseCaches(false);
        con.setRequestMethod("POST");
        con.getOutputStream().write(postDataBytes);

        BufferedReader  reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
        StringBuffer buffer = new StringBuffer();
        for (String line = reader.readLine(); line != null; line = reader.readLine())
        {
            buffer.append(line);
        }

        JSONObject json = new JSONObject(buffer.toString());
        String accessToken = json.getString("access_token");
        return accessToken;
    }
    catch (Exception ex)
    {
        ex.printStackTrace(); 
    }
    return null;
}
_

Google PlayにアクセスするAndroid developer api)の場合、アクセストークンを取得するには、以前の更新トークンを渡す必要があります

_private String getAccessToken(String refreshToken){

HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://accounts.google.com/o/oauth2/token");
try 
{
    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
    nameValuePairs.add(new BasicNameValuePair("grant_type",    "refresh_token"));
    nameValuePairs.add(new BasicNameValuePair("client_id",     GOOGLE_CLIENT_ID));
    nameValuePairs.add(new BasicNameValuePair("client_secret", GOOGLE_CLIENT_SECRET));
    nameValuePairs.add(new BasicNameValuePair("refresh_token", refreshToken));
    post.setEntity(new UrlEncodedFormEntity(nameValuePairs));

    org.Apache.http.HttpResponse response = client.execute(post);
    BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
    StringBuffer buffer = new StringBuffer();
    for (String line = reader.readLine(); line != null; line = reader.readLine())
    {
        buffer.append(line);
    }

    JSONObject json = new JSONObject(buffer.toString());
    String accessToken = json.getString("access_token");

    return accessToken;

}
catch (IOException e) { e.printStackTrace(); }

return null;
}
_

リソースリンク:

このsamplesと_resource link_が問題の解決と_access token_へのアクセスに役立つことを願っています。


400不正リクエストとは

Ans:クエリが無効だったことを示します。親IDがないか、リクエストされたディメンションまたは指標の組み合わせが無効でした。

推奨されるアクション:APIクエリを機能させるには、APIクエリに変更を加える必要があります。

_HTTP/1.1 400 Bad Request error_の場合、 別の答え を通過できます。 これは、_which Host you need to use_および適用する必要がある条件について理解するのに役立ちます

トークンが期限切れになる理由?トークンの制限は何ですか?

トークンは、次のいずれかの理由で機能しなくなる可能性があります。

  1. ユーザーにはrevokedアクセス権があります。
  2. トークンは_six months_に使用されていません。
  3. _user changed passwords_およびトークンには、Gmail、カレンダー、連絡先、またはハングアウトのスコープが含まれています。
  4. ユーザーアカウントには_exceeded a certain number of token requests_があります。

_currently a limit of 25 refresh tokens per user account per client_があります。制限に達した場合、新しいトークンを作成すると、警告なしに最も古いトークンが自動的に無効になります。この制限はサービスアカウントには適用されません。

どの予防策に従うべきですか?

注意事項-1:

一部のリクエストでは、ユーザーがGoogleアカウントでログインする認証手順が必要です。ログイン後、ユーザーは、アプリケーションが要求している権限を許可するかどうかを尋ねられます。このプロセスはユーザーの同意と呼ばれます。

ユーザーが許可を与えると、Google Authorization Serverはアプリケーションにアクセストークン(またはアプリケーションがアクセストークンの取得に使用できる認証コード)を送信します。ユーザーが権限を付与しない場合、サーバーはエラーを返します。

注意事項-2:

Google+ APIのアクセストークンが発行された場合、Google Contacts APIへのアクセスは許可されません。ただし、同様の操作で、そのアクセストークンをGoogle+ APIに複数回送信できます。

注意事項-3:

通常、アクセストークンの有効期限は1時間で、それを使用しようとするとエラーが発生します。 Google Credential は、トークンを自動的に「更新」します。これは、単に新しいアクセストークンを取得することを意味します。

リフレッシュトークンを安全な長期ストレージに保存し、有効な限り、トークンを使用し続けます。クライアントとユーザーの組み合わせごと、およびすべてのクライアントのユーザーごとに発行される更新トークンの数には制限が適用されますが、これらの制限は異なります。アプリケーションが制限の1つを超えるのに十分な更新トークンを要求すると、古い更新トークンは機能しなくなります。

11
SkyWalker

正しいエンドポイントを使用していません。 authURLhttps://www.googleapis.com/oauth2/v4/tokenに変更してみてください

ドキュメントから:

このトークンリクエストを行うには、HTTP POSTリクエストを/ oauth2/v4/tokenエンドポイントに送信します

実際のリクエストは次のようになります。

POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/v6xr77ewYqhvHSyW6UJ1w7jKwAzu&
client_id=8819981768.apps.googleusercontent.com&
client_secret=your_client_secret&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code

リファレンスhttps://developers.google.com/identity/protocols/OAuth2InstalledApp#handlingtheresponse

3
newhouse

私にとってはあなたのリクエストは問題ありません、Curlを使用して試しましたが、「invalid_grant」が失敗した理由とともに「HTTP/1.1 400 Bad Request」も取得します。

curl -X POST https://www.googleapis.com/oauth2/v4/token -d 'code=4/SVisuz_x*********************&client_id=*******************7vet.apps.googleusercontent.com&client_secret=***************&redirect_uri=https://oauth2-login-demo.appspot.com/code&grant_type=authorization_code'

受信(HTTP/1.1 400 Bad Request):

{
 "error": "invalid_grant",
 "error_description": "Code was already redeemed."
}

ApacheからHttpClientを使用する:

URL obj = new URL(authURL);
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(authURL);
post.addHeader("Content-Type", "application/x-www-form-urlencoded");
post.addHeader("Host", "www.googleapis.com");
post.setEntity(new StringEntity(strBuild.toString()));

HttpResponse resp = client.execute(post);
System.out.println(resp.getStatusLine());
System.out.println(EntityUtils.toString(resp.getEntity()));

私のコンソールに表示されます:

HTTP/1.1 400 Bad Request
{
 "error": "invalid_grant",
 "error_description": "Code was already redeemed."
}

使用しているコードはまだ有効ですか?新しいもので試すことができますか?

まず、このページを見る必要があります:

https://developers.google.com/gmail/api/auth/web-server#create_a_client_id_and_client_secret

クエリパラメータコードに表示される値は、アクセストークンを取得するためにGoogleに投稿する必要がある文字列です。

Webサーバーは認証コードを受信すると、認証コードをアクセストークンと更新トークンに交換します。このリクエストはHTTPSですPOST URLへ https://www.googleapis.com/oauth2/v3/token POST/oauth2/v3/token HTTP/1.1 content-type:application/x-www-form-urlencoded

code = 4/v4-CqVXkhiTkn9uapv6V0iqUmelHNnbLRr1EbErzkQw#&redirect_uri =&client_id =&scope =&client_secret = ************&grant_type = authorization_code https://developers.google.com/identity/protocols/OAuth2WebServer

0
Fırat Kocabay

参照: https://developers.google.com/Android-publisher/authorization

「リフレッシュトークン」と呼ばれる認証コードがすでにあります。安全な場所に保管してください。 「更新トークン」を使用して「アクセストークン」を生成できます。

「アクセストークン」を取得するには、以下のURLに投稿リクエストを行ってください

https://accounts.google.com/o/oauth2/token

パラメーター:

  • grant_type
  • クライアントID
  • client_secret
  • リフレッシュトークン

「grant_type」は「refresh_token」である必要があります

私たちはPHPを使用して同じことをしています、これは参考のためにPHPのコードです

    $curl = curl_init();

    curl_setopt_array($curl, array(
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_URL => 'https://accounts.google.com/o/oauth2/token',
    CURLOPT_USERAGENT => 'Pocket Experts Services',
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => array(
    "grant_type" => "refresh_token",
    "client_id" => $GOOGLE_CLIENT_ID,
    "client_secret" => $GOOGLE_CLIENT_SECRET,
    "refresh_token" => $GOOGLE_REFRESH_TOKEN,
    )));


    // Send the request & save response to $resp
    $resp = curl_exec($curl);

それがあなたを助けることを願っています。

0
Umang Joshi