Как получить Refresh Token для Google Ads API: Полное руководство

Что такое Refresh Token и зачем он нужен для Google Ads API?

При работе с Google Ads API для программного управления рекламными кампаниями требуется авторизация. Refresh Token (токен обновления) является критически важным элементом в этом процессе. Это долгосрочный (как правило, бессрочный, если не будет отозван пользователем или Google) токен, который используется для получения новых Access Token (токенов доступа) без необходимости повторного запроса разрешения у пользователя.

Google Ads API использует Access Token для аутентификации каждого запроса. Срок действия Access Token ограничен (обычно 30-60 минут). Без Refresh Token вам пришлось бы постоянно переавторизовываться, что крайне непрактично для автоматизированных процессов и фоновых задач.

Наличие валидного Refresh Token позволяет вашему приложению получать новые Access Token по мере необходимости, обеспечивая непрерывный доступ к API от имени пользователя или аккаунта.

Отличия Refresh Token от Access Token

Понимание разницы между этими двумя типами токенов является фундаментальным для корректной работы с OAuth 2.0 потоком, используемым Google Ads API.

Access Token: Краткосрочный, используется для аутентификации конкретных запросов к API. Несет в себе информацию оGranted разрешениях. Имеет ограниченный срок действия (минуты).

Refresh Token: Долгосрочный (или бессрочный), используется только для получения новых Access Token. Не используется напрямую для запросов к API. Позволяет приложению работать в фоновом режиме без постоянного участия пользователя.

Refresh Token выдается один раз в процессе первоначальной авторизации и должен быть надежно сохранен. Access Token получается многократно по запросу с использованием Refresh Token.

Необходимые предварительные шаги: создание проекта в Google Cloud Console и настройка OAuth

Перед тем как получить Refresh Token, вам необходимо выполнить несколько подготовительных шагов в Google Cloud Console.

Создайте проект в Google Cloud Console: Если у вас его нет, создайте новый проект. Это рабочее пространство для ваших приложений Google Cloud.

Включите Google Ads API: Перейдите в раздел "API & Services" -> "Library", найдите "Google Ads API" и включите его для вашего проекта.

Настройте OAuth Consent Screen: Этот экран видит пользователь, когда дает вашему приложению разрешение на доступ к своим данным. Укажите название приложения, email поддержки и другую необходимую информацию. Важно добавить необходимые области доступа (scopes) для Google Ads API. Минимальный scope для доступа к данным кампаний обычно 'https://www.googleapis.com/auth/adwords'.

Создайте учетные данные OAuth 2.0: Перейдите в раздел "API & Services" -> "Credentials". Создайте "OAuth client ID".

Выберите тип приложения. Для серверных приложений, работающих с пользовательскими данными, часто используют "Web application". Для десктопных или скриптов, запускаемых локально, можно выбрать "Desktop app". Выбор типа влияет на способ получения токена.

Для "Web application" укажите Authorized redirect URIs. Это URL-адреса, на которые Google будет перенаправлять пользователя после успешной авторизации, передавая Authorization Code. Для локальных скриптов или тестирования часто используют 'http://localhost' или специфический URI типа 'urn:ietf:wg:oauth:2.0:oob' (Out-of-Band) для получения кода в браузере и последующего его копирования в консоль.

После создания вы получите Client ID и Client Secret. Эти данные являются конфиденциальными и будут использоваться для обмена Authorization Code на Access и Refresh токены.

Убедитесь, что ваш OAuth client ID настроен правильно с необходимыми redirect URIs и scopes, прежде чем переходить к следующему шагу получения токена.

Получение Refresh Token через OAuth 2.0 Playground

OAuth 2.0 Playground — это интерактивный инструмент от Google, который позволяет легко пройти поток OAuth 2.0 и получить Access Token и Refresh Token для тестирования или однократного использования.

Шаг 1: Переход на OAuth 2.0 Playground и настройка конфигурации

Откройте https://developers.google.com/oauthplayground/ (примечание: избегаем ссылок, но URL инструмента полезен). В правой части страницы найдите блок "Configuration".

Установите флажок "Use your own OAuth credentials".

Введите свой Client ID и Client Secret, полученные в Google Cloud Console на предыдущем шаге.

Убедитесь, что "OAuth flow" установлен как "Server-side", а "Access token location" — "Authorization header (recommended)".

Шаг 2: Выбор API Google Ads (AdWords) и необходимых разрешений (scopes)

В левой части страницы "Step 1 Select & authorize APIs", прокрутите список сервисов Google.

Найдите "Google Ads API" (может отображаться как "AdWords API v201809" или аналогично, выберите самую актуальную версию, если есть выбор; для современных версий API v10+ просто "Google Ads API").

Разверните раздел и выберите необходимые scopes. Для большинства операций с аккаунтами Google Ads достаточно 'https://www.googleapis.com/auth/adwords'. Выберите этот scope.

Нажмите кнопку "Authorize APIs".

Шаг 3: Авторизация приложения и получение Authorization Code

После нажатия "Authorize APIs" вы будете перенаправлены на стандартный экран авторизации Google. Выберите аккаунт Google, который имеет доступ к аккаунту Google Ads, с которым вы собираетесь работать (или является владельцем этого аккаунта), и дайте разрешение вашему приложению (представленному названием, которое вы указали на экране согласия OAuth).

После успешной авторизации Google перенаправит вас обратно на OAuth 2.0 Playground. В центральной части страницы, в разделе "Step 2 Exchange authorization code for tokens", вы увидите Authorization Code.

Шаг 4: Обмен Authorization Code на Refresh Token

На том же шаге 2 "Exchange authorization code for tokens" в OAuth 2.0 Playground, после получения Authorization Code, нажмите кнопку "Exchange authorization code for tokens".

Playground выполнит POST-запрос к эндпоинту токенов Google OAuth 2.0 (https://oauth2.googleapis.com/token), используя ваш Client ID, Client Secret, Authorization Code и redirect URI (https://developers.google.com/oauthplayground).

В ответе (раздел "Step 3 Configure & use API") вы получите JSON-объект, содержащий:

access_token: Ваш первый Access Token.

expires_in: Срок действия Access Token в секундах.

refresh_token: Ваш искомый Refresh Token.

scope: Scope, на который вы получили разрешение.

token_type: Тип токена (обычно Bearer).

Скопируйте значение refresh_token. Это токен, который вам нужен для дальнейшего использования в своих приложениях. Он не будет показан снова через этот поток, поэтому сохраните его немедленно.

Получение Refresh Token с использованием собственного OAuth 2.0 клиента

Для автоматизации или интеграции в существующие приложения, вам потребуется реализовать OAuth 2.0 поток программно. Этот подход дает больше контроля и необходим для production-систем.

Создание и настройка OAuth 2.0 клиента в Google Cloud Console

Этот шаг уже был описан в предварительных шагах. Убедитесь, что у вас есть:

Проект Google Cloud с включенным Google Ads API.

Настроенный экран согласия OAuth.

Учетные данные типа "Web application" или "Desktop app" с корректно настроенными Authorized redirect URIs. Для серверных приложений это должен быть URI на вашем сервере, способный принять редирект от Google. Для скриптов часто используется 'urn:ietf:wg:oauth:2.0:oob'.

Получены Client ID и Client Secret.

Генерация URL для авторизации с необходимыми параметрами (client_id, redirect_uri, scope, response_type)

Первый шаг в коде — это создание URL для авторизации. Ваше приложение должно перенаправить пользователя на этот URL, чтобы тот мог войти в свой аккаунт Google и дать разрешение.

Основной URL для запроса авторизации: https://accounts.google.com/o/oauth2/v2/auth

К нему добавляются следующие GET-параметры:

client_id: Ваш Client ID.

redirect_uri: Один из авторизованных URI, указанных в Google Cloud Console. Должен точно совпадать.

scope: Запрашиваемые области доступа, разделенные пробелами. Минимум 'https://www.googleapis.com/auth/adwords'.

response_type: Должен быть 'code' для получения Authorization Code.

access_type: Установите 'offline' чтобы Google выдал Refresh Token. Это критически важно! Без 'access_type=offline' вы получите только Access Token.

prompt: Рекомендуется установить 'consent' при первом запросе, чтобы гарантировать показ экрана согласия и получение Refresh Token. Для последующих авторизаций, когда Refresh Token уже есть, можно опустить или использовать 'auto'.

Пример формирования URL (псевдокод):

AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth' +
           '?client_id=' + YOUR_CLIENT_ID +
           '&redirect_uri=' + YOUR_REDIRECT_URI_ENCODED +
           '&scope=' + 'https://www.googleapis.com/auth/adwords' +
           '&response_type=code' +
           '&access_type=offline' +
           '&prompt=consent'

Ваше приложение должно сгенерировать этот URL и либо перенаправить на него пользователя (в веб-приложении), либо вывести его в консоль с просьбой пользователю открыть его в браузере (в десктопном/скриптовом приложении).

Обработка ответа от Google и получение Authorization Code

После того как пользователь авторизуется и даст разрешение, Google перенаправит его обратно на ваш redirect_uri. Authorization Code будет передан как GET-параметр code в URL перенаправления.

Пример URL, на который перенаправит Google:

YOUR_REDIRECT_URI?code=YOUR_AUTHORIZATION_CODE&scope=...

Ваше приложение, слушающее на YOUR_REDIRECT_URI, должно извлечь значение параметра code из этого запроса. Это и есть Authorization Code, который нужен для следующего шага.

Если вы использовали 'urn:ietf:wg:oauth:2.0:oob' в качестве redirect_uri, Google отобразит Authorization Code прямо в браузере, и пользователь должен будет скопировать его и вставить в ваше консольное приложение.

Использование Authorization Code для получения Refresh Token через POST запрос к Google

Последний шаг — обмен полученного Authorization Code на Access Token и Refresh Token. Это делается путем выполнения POST-запроса к эндпоинту токенов Google: https://oauth2.googleapis.com/token.

Этот запрос должен содержать следующие параметры в теле (в формате application/x-www-form-urlencoded или JSON, хотя form-urlencoded более типичен для этого эндпоинта):

code: Полученный на предыдущем шаге Authorization Code.

client_id: Ваш Client ID.

client_secret: Ваш Client Secret.

redirect_uri: Тот же redirect_uri, что использовался на шаге авторизации.

grant_type: Должен быть 'authorization_code'.

Пример структуры POST-запроса:

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

code=YOUR_AUTHORIZATION_CODE&
client_id=YOUR_CLIENT_ID&
client_secret=YOUR_CLIENT_SECRET&
redirect_uri=YOUR_REDIRECT_URI_ENCODED&
grant_type=authorization_code

В ответ на этот запрос вы получите JSON-объект, идентичный тому, что выдал OAuth 2.0 Playground на шаге 4, содержащий access_token, expires_in, refresh_token, scope, token_type. Выделите и сохраните refresh_token.

Безопасное хранение и использование Refresh Token

Refresh Token — это ключ к аккаунту Google Ads пользователя (через получение Access Token). Его компрометация может привести к несанкционированному доступу. Поэтому крайне важно обеспечить его безопасное хранение и использование.

Рекомендации по безопасному хранению Refresh Token

Не храните в коде: Никогда не встраивайте Refresh Token непосредственно в исходный код вашего приложения.

Используйте переменные окружения: Для небольших скриптов или локальных запусков можно использовать переменные окружения.

Реклама

Секретные менеджеры: Для облачных или серверных приложений используйте специализированные сервисы управления секретами (например, Google Secret Manager, AWS Secrets Manager, HashiCorp Vault). Это наиболее безопасный подход.

Зашифрованные базы данных: Если необходимо хранить токены для многих пользователей, используйте базу данных, где поля с Refresh Token зашифрованы.

Ограничьте доступ: Предоставьте доступ к хранимым Refresh Token только тем компонентам системы, которым это действительно необходимо.

Примеры использования Refresh Token для получения Access Token на различных языках программирования (PHP, Python, Java)

Получение нового Access Token с использованием Refresh Token требует POST-запроса к тому же эндпоинту https://oauth2.googleapis.com/token, но с другим grant_type.

Параметры POST-запроса для обновления токена:

client_id: Ваш Client ID.

client_secret: Ваш Client Secret.

refresh_token: Ваш сохраненный Refresh Token.

grant_type: Должен быть 'refresh_token'.

В ответ вы получите новый access_token, expires_in, scope, token_type. Обратите внимание: Refresh Token не выдается повторно в этом запросе, если он не был отозван.

Примеры кода:

Python:

import requests
import os # Для безопасного получения секрета из окружения

# Получаем учетные данные из безопасного источника (например, переменные окружения)
CLIENT_ID: str = os.environ.get("GOOGLE_ADS_CLIENT_ID")
CLIENT_SECRET: str = os.environ.get("GOOGLE_ADS_CLIENT_SECRET")
REFRESH_TOKEN: str = os.environ.get("GOOGLE_ADS_REFRESH_TOKEN")

# URL эндпоинта для обмена токенов
TOKEN_URL: str = 'https://oauth2.googleapis.com/token'

def refresh_access_token(client_id: str, client_secret: str, refresh_token: str) -> dict:
    """
    Обменивает Refresh Token на новый Access Token.

    Args:
        client_id: Ваш Client ID Google OAuth.
        client_secret: Ваш Client Secret Google OAuth.
        refresh_token: Действующий Refresh Token.

    Returns:
        Словарь с новым Access Token и его метаданными, либо пустой словарь в случае ошибки.
    """
    payload = {
        'client_id': client_id,
        'client_secret': client_secret,
        'refresh_token': refresh_token,
        'grant_type': 'refresh_token'
    }

    try:
        response = requests.post(TOKEN_URL, data=payload)
        response.raise_for_status() # Вызовет исключение для bad responses (4xx or 5xx)
        token_data: dict = response.json()
        # Ожидаемый ответ содержит 'access_token', 'expires_in', 'token_type'
        if 'access_token' in token_data:
            print("Successfully refreshed Access Token.")
            return token_data
        else:
            print("Error: 'access_token' not found in response.")
            print("Response:", token_data)
            return {}

    except requests.exceptions.RequestException as e:
        print(f"Error refreshing token: {e}")
        return {}

# Пример использования:
if CLIENT_ID and CLIENT_SECRET and REFRESH_TOKEN:
    new_tokens: dict = refresh_access_token(CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN)
    if new_tokens:
        access_token: str = new_tokens.get('access_token', '')
        expires_in: int = new_tokens.get('expires_in', 0)
        print(f"New Access Token: {access_token}")
        print(f"Expires in: {expires_in} seconds")
        # Теперь используйте access_token для запросов к Google Ads API
else:
    print("Error: Missing environment variables for credentials.")

PHP:

 $clientId,
        'client_secret' => $clientSecret,
        'refresh_token' => $refreshToken,
        'grant_type' => 'refresh_token',
    ];

    $options = [
        'http' => [
            'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
            'method'  => 'POST',
            'content' => http_build_query($payload),
            // Игнорируем ошибки SSL для простоты примера, в production так делать не стоит!
            'verify_peer' => false,
            'verify_peer_name' => false,
        ],
    ];

    $context  = stream_context_create($options);
    $result = @file_get_contents(TOKEN_URL, false, $context);

    if ($result === FALSE) {
        // Обработка ошибки (например, logging $http_response_header)
        error_log("Error refreshing token: " . var_export($http_response_header, true));
        return null;
    }

    $tokenData = json_decode($result, true);

    if (isset($tokenData['access_token'])) {
        echo "Successfully refreshed Access Token.\n";
        return $tokenData;
    } else {
        error_log("Error: 'access_token' not found in response. Response: " . var_export($tokenData, true));
        return null;
    }
}

// Пример использования:
if ($clientId && $clientSecret && $refreshToken) {
    $newTokens = refreshAccessToken($clientId, $clientSecret, $refreshToken);
    if ($newTokens) {
        $accessToken = $newTokens['access_token'] ?? '';
        $expiresIn = $newTokens['expires_in'] ?? 0;
        echo "New Access Token: " . $accessToken . "\n";
        echo "Expires in: " . $expiresIn . " seconds\n";
        // Теперь используйте $accessToken для запросов к Google Ads API
    } else {
         echo "Failed to refresh access token.\n";
    }
} else {
    echo "Error: Missing environment variables for credentials.\n";
}

?>

Java (с использованием Apache HttpClient):

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.logging.Logger;

public class TokenRefresher {

    private static final Logger LOGGER = Logger.getLogger(TokenRefresher.class.getName());
    private static final String TOKEN_URL = "https://oauth2.googleapis.com/token";

    // Получаем учетные данные из безопасного источника (например, переменные окружения или System properties)
    private static final String CLIENT_ID = System.getenv("GOOGLE_ADS_CLIENT_ID");
    private static final String CLIENT_SECRET = System.getenv("GOOGLE_ADS_CLIENT_SECRET");
    private static final String REFRESH_TOKEN = System.getenv("GOOGLE_ADS_REFRESH_TOKEN");

    /**
     * Обменивает Refresh Token на новый Access Token.
     *
     * @param clientId Ваш Client ID Google OAuth.
     * @param clientSecret Ваш Client Secret Google OAuth.
     * @param refreshToken Действующий Refresh Token.
     *
     * @return JsonNode с новым Access Token и его метаданными, либо null в случае ошибки.
     */
    public static JsonNode refreshAccessToken(String clientId, String clientSecret, String refreshToken) {
        if (clientId == null || clientId.isEmpty() || clientSecret == null || clientSecret.isEmpty() || refreshToken == null || refreshToken.isEmpty()) {
            LOGGER.severe("Missing credentials for token refresh.");
            return null;
        }

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(TOKEN_URL);

            // Параметры запроса в формате application/x-www-form-urlencoded
            String requestBody = String.format(
                    "client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token",
                    clientId,
                    clientSecret,
                    refreshToken
            );

            httpPost.setEntity(new StringEntity(requestBody));
            httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");

            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                String responseBody = EntityUtils.toString(response.getEntity());
                ObjectMapper mapper = new ObjectMapper();
                JsonNode tokenData = mapper.readTree(responseBody);

                if (response.getStatusLine().getStatusCode() == 200) {
                    LOGGER.info("Successfully refreshed Access Token.");
                    // Ожидаемый ответ содержит 'access_token', 'expires_in', 'token_type'
                    if (tokenData.has("access_token")) {
                        return tokenData;
                    } else {
                        LOGGER.warning("Error: 'access_token' not found in response. Response: " + responseBody);
                        return null;
                    }
                } else {
                    LOGGER.severe("Error refreshing token: " + response.getStatusLine().getStatusCode() + " - " + responseBody);
                    return null;
                }
            }

        } catch (IOException e) {
            LOGGER.severe("Exception during token refresh: " + e.getMessage());
            return null;
        }
    }

    public static void main(String[] args) {
        // Пример использования:
        JsonNode newTokens = refreshAccessToken(CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN);

        if (newTokens != null) {
            String accessToken = newTokens.get("access_token").asText();
            int expiresIn = newTokens.get("expires_in").asInt();
            System.out.println("New Access Token: " + accessToken);
            System.out.println("Expires in: " + expiresIn + " seconds");
            // Теперь используйте accessToken для запросов к Google Ads API
        } else {
            System.out.println("Failed to refresh access token. Check logs for details.");
        }
    }
}

В реальных приложениях рекомендуется использовать официальные клиентские библиотеки Google API, которые абстрагируют большую часть логики OAuth 2.0, включая управление Access Token и их обновление с помощью Refresh Token.

Обработка ошибок и исключений при работе с Refresh Token (токен недействителен, отозван и т.д.)

При использовании Refresh Token могут возникать ошибки:

Недействительный Refresh Token (invalid_grant): Это самая частая ошибка. Происходит, если токен был отозван пользователем (например, через настройки безопасности Google аккаунта), либо Google по какой-то причине его аннулировал. Также может произойти, если вы пытаетесь использовать Refresh Token, который был выдан для другого Client ID или для другого типа клиента (web vs desktop). В этом случае необходимо пройти весь OAuth 2.0 поток авторизации заново, чтобы получить новый Refresh Token.

Неверные учетные данные клиента (invalid_client): Ваш Client ID или Client Secret указаны неверно.

Превышен лимит запросов: Слишком частые попытки обновления токена могут привести к временным ограничениям.

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

Заключение

Refresh Token является основой для создания надежных и автоматизированных интеграций с Google Ads API. Он позволяет вашим приложениям работать непрерывно, получая Access Token по мере необходимости без ручного вмешательства.

Получить Refresh Token можно как через удобный инструмент OAuth 2.0 Playground для тестирования и однократного использования, так и программно, реализовав OAuth 2.0 поток авторизации в своем приложении.

Ключевыми аспектами являются:

Правильная настройка проекта в Google Cloud Console, включая экран согласия и учетные данные OAuth.

Запрос scope 'https://www.googleapis.com/auth/adwords'.

Использование параметра access_type=offline при запросе авторизации для получения Refresh Token.

Надежное и безопасное хранение полученного Refresh Token.

Реализация логики обмена Refresh Token на новый Access Token при истечении срока действия текущего Access Token.

Обработка возможных ошибок, в частности invalid_grant, требующей повторной авторизации.

Следуя этим шагам и рекомендациям, вы сможете успешно получить и использовать Refresh Token для своих задач по автоматизации Google Ads.

Полезные советы и рекомендации по работе с Google Ads API

Используйте клиентские библиотеки: Google предоставляет официальные клиентские библиотеки для многих языков (Java, .NET, PHP, Python, Ruby, Node.js), которые упрощают работу с API и OAuth 2.0.

Управление аккаунтами: Используйте менеджерские аккаунты (MCC) для работы с несколькими клиентскими аккаунтами Google Ads через один Refresh Token и учетные данные API.

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

Квоты и лимиты: Ознакомьтесь с дневными лимитами запросов к Google Ads API и планируйте свою работу соответственно.

Логирование: Внедрите детальное логирование запросов к API и ответов, включая ошибки авторизации.

Часто задаваемые вопросы (FAQ) по получению и использованию Refresh Token

Как долго действует Refresh Token? Обычно бессрочно, пока не будет отозван пользователем или Google. Существуют редкие исключения, но рассчитывайте на его долгосрочность.

Могу ли я получить Refresh Token для аккаунта MCC? Да, вы авторизуете приложение от имени пользователя, у которого есть доступ к MCC. Полученный токен позволит работать с этим MCC и всеми связанными с ним клиентскими аккаунтами (при наличии соответствующих разрешений у пользователя).

Что делать, если Refresh Token перестал работать? Скорее всего, он был отозван. Необходимо пройти процесс авторизации заново, чтобы получить новый Refresh Token.

Можно ли получить несколько Refresh Token для одного аккаунта? Да, одно и то же приложение может пройти авторизацию несколько раз, каждый раз получая новый Refresh Token. Пользователь также может выдать разрешения разным приложениям, каждое из которых получит свой токен.

Дополнительные ресурсы и документация

Для более глубокого изучения и решения специфических задач обратитесь к официальной документации Google Ads API и документации Google Identity Platform (OAuth 2.0).


Добавить комментарий