Как получить токен доступа, используя 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

Ответы

Ответ 1

Как получить токен доступа с помощью gmail api?

Ans: В соответствии с в следующем учебнике вы используете OAuth 2.0. Таким образом, существует базовый шаблон для доступа к API Google с помощью OAuth 2.0. Он следует за 4 этапами:

  • Получите учетные данные OAuth 2.0 в консоли разработчика Google.
  • Получить токен доступа с сервера авторизации Google.
  • Отправлять токен доступа в API.
  • При необходимости обновите токен доступа.

Подробнее см. в руководстве - Использование OAuth 2.0 для доступа к API Google

Вы должны посетить Google Developers Console, чтобы получить учетные данные OAuth 2.0, такие как client ID и client secret, которые известны как Google, так и ваше приложение


Анализ корневой причины:

Выпуск-1:

Изучив свой код, некоторые из них не найдены. Если ваш код работает гладко, тогда код всегда дает пустую строку. Поскольку ваш метод AccessToken() всегда возвращает return "";

Выпуск-2:

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

Блок try catch будет блокировать исключения. Потому что, похоже, вы не правильно завершили свой код. Вы пропустили encoding, а также использовали JSONObject, который готовит токен доступа. Таким образом, он дает результат как

Ошибка.

Решение:

Я понял, что ваш код похож на этот учебник

Поскольку вашему решению требуется больше изменений для решения проблемы. Поэтому я предлагаю вам использовать 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 вам необходимо пройти предыдущий токен обновления, чтобы получить токен доступа

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: Указывает, что запрос был недопустимым. Отсутствует идентификатор родителя, или комбинация запрошенных размеров или показателей недействительна.

Рекомендуемое действие: Вам нужно внести изменения в запрос API, чтобы он работал.

Для HTTP/1.1 400 Bad Request error вы можете пройти через мой другой ответить. Это поможет вам понять смысл which host you need to use и какие условия вам необходимо применить.

Почему токен истекает? Каков предел токена?

Токен может перестать работать по одной из следующих причин:

  • Пользователь имеет revoked доступ.
  • Токен не использовался для six months.
  • user changed passwords и токен содержит Gmail, Календарь, Контакты или Hangouts.
  • У учетной записи пользователя есть exceeded a certain number of token requests.

Существует currently a limit of 25 refresh tokens per user account per client. Если предел достигнут, создание нового токена автоматически аннулирует старейший токен без предупреждения. Это ограничение не распространяется на учетные записи служб.

Какие меры предосторожности следует соблюдать?

Меры предосторожности - 1:

Некоторые запросы требуют этапа аутентификации, на котором пользователь входит в систему с их учетной записью Google. После входа в систему пользователь спрашивает, они готовы предоставить разрешения, которые ваша заявка запрос. Этот процесс называется пользовательским соглашением.

Если пользователь предоставляет разрешение, Сервер авторизации Google отправляет вашему приложению токен доступа (или код авторизации, который ваше приложение может использовать для получения токена доступа). Если пользователь делает не предоставлять разрешение, сервер возвращает ошибку.

Меры предосторожности - 2:

Если для Google+ API выпущен токен доступа, он не предоставляет доступ к API контактов Google. Однако вы можете отправить этот доступ токен API Google+ несколько раз для аналогичных операций.

Меры предосторожности - 3:

Ток доступа обычно имеет срок годности 1 час, после который вы получите сообщение об ошибке, если попытаетесь его использовать. Google Credentialзаботится о том, чтобы автоматически "обновлять" токен, что просто означает получение нового токена доступа.

Сохранить токены обновления в безопасном долгосрочном хранилище и продолжать использовать до тех пор, пока они остаются в силе. Пределы применяются к числу обновлять токены, которые выдаются на комбинацию клиент-пользователь, и за пользователь на всех клиентах, и эти ограничения различны. Если ваш приложения требуют достаточно обновить токены, чтобы пройти один из ограничения, старые токены обновления перестают работать.

Ответ 2

Вы не используете правую конечную точку. Попробуйте изменить authURL на https://www.googleapis.com/oauth2/v4/token

Из документации:

Чтобы выполнить этот токен, отправьте запрос HTTP POST в конечную точку /oauth 2/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

Для меня ваш запрос прекрасен, я попробовал его с помощью Curl, я также получил "HTTP/1.1 400 Bad Request", из-за которого он не удалось "invalid_grant":

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."
}

Теперь использование HttpClient из Apache:

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."
}

Вы уверены, что код, который вы используете, по-прежнему действует? Вы можете попробовать с новым?

Ответ 4

Во-первых, вы должны посмотреть эту страницу:

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

Значение, которое вы видите в коде параметра запроса, - это строка, которую вы должны отправить в Google, чтобы получить токен доступа.

После того, как веб-сервер получит код авторизации, он может обменять код авторизации для токена доступа и токена обновления. Этот запрос представляет собой HTTPS POST для URL https://www.googleapis.com/oauth2/v3/token POST/oauth2/v3/токен HTTP/1.1 content-type: application/x-www-form-urlencoded

код = 4/v4-CqVXkhiTkn9uapv6V0iqUmelHNnbLRr1EbErzkQw # & redirect_uri = & client_id = & сфера = & client_secret = ************ & grant_type = authorization_code https://developers.google.com/identity/protocols/OAuth2WebServer

Ответ 5

Думаю, я понимаю, что неправильно:

  • как сказал @newhouse, вы должны отправить сообщение https://www.googleapis.com/oauth2/v4/token, а не https://accounts.google.com/o/oauth2/token (@newhouse я дал вам +1:))

    (https://www.googleapis.com/oauth2/v4/token для получения authorization_code и https://accounts.google.com/o/oauth2/token для получения code).

  • Вы не можете использовать один и тот же code более одного раза.

    Все остальное выглядит так, поэтому, если вы продолжаете получать 400, вы, вероятно, пытаетесь использовать code, вы получили более одного раза (тогда вы будете получать 400 каждый раз, снова и снова).

* Вы также должны потерять con.setRequestProperty("Host", "www.googleapis.com");

Ответ 6

Refer: https://developers.google.com/android-publisher/authorization

У вас уже есть код авторизации, который называется "refresh token". Пожалуйста, держите его в надежном месте. Вы можете использовать "токен обновления" для создания "токена доступа".

Чтобы получить "токен доступа", пожалуйста, отправьте запрос на следующий URL

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

Параметры:

  • grant_type
  • client_id
  • client_secret
  • refresh_token

где "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);

Надеюсь, это поможет вам.