OAuth 2.0 访问令牌和刷新令牌

OAuth 2.0 Access Tokens and Refresh Tokens

我很难理解刷新和访问令牌的正确用法。我知道刷新令牌与授权相关,访问令牌与 authentication.I 相关,我想更好地解释我的用例,以便有人可以在这里帮助我。我在 Google Merchant Center 中有一个多帐户中心。我想在我的代码中集成最新的 OAuth 2.0 身份验证机制。我做到了并且可以成功进行身份验证。我使用 Google 构建凭据对象的凭据机制,并在对 google 的 httprequest 期间使用 httprequestinitializer 机制注入。当创建 google 凭据对象时,我发现当我执行 googleCredential.getAccessToken() 时没有访问令牌,但是当我执行 googleCredential.refreshToken() 然后执行 googleCredential.getAccessToken() ,我得到一个 accessToken。但是,我正在测试如何创建令牌,并且我没有在请求中明确地将这些令牌传递给 google。我传递的只是带有客户端机密和其他私钥的 googleCredential 对象。我正在做的任务只是通过 cron 脚本将子帐户产品提要上传到 google。

我的问题是,

  1. 在此处传递 googleCredential 对象时是否必须处理此处的刷新令牌? (假设脚本运行超过一天)
  2. 什么时候应该使用刷新令牌和访问令牌,在上述用例中什么对我来说是正确的选择? (虽然现在除了 googleCredential Object 之外我没有明确传递任何东西)
  3. 访问令牌和刷新令牌的有效期是多少(与上述用例无关,只是想知道,有人说刷新令牌为 14 天,有人说无限期直到用户撤销访问等)

如果有人澄清我并把我拉出来,我会很饱。我知道这个平台主要是为了澄清代码上的问题,但我 google 论坛也无济于事。所以在这里发帖。

抱歉太冗长了。

提前致谢。

所谓的 OfflineCredentials 需要 刷新令牌。这些是凭据,可以由应用程序使用,这些应用程序在浏览器中不是 运行(例如桌面应用程序或一些没有 UI 的批处理),因此无法执行 OAuth2 流程。

请看Using OAuth 2.0 to Access Google APIs

  1. Refresh the access token, if necessary.

Access tokens have limited lifetimes. If your application needs access to a Google API beyond the lifetime of a single access token, it can obtain a refresh token. A refresh token allows your application to obtain new access tokens.

Note: Save refresh tokens in secure long-term storage and continue to use them as long as they remain valid. Limits apply to the number of refresh tokens that are issued per client-user combination, and per user across all clients, and these limits are different. If your application requests enough refresh tokens to go over one of the limits, older refresh tokens stop working.

Offline Access!

发送更多信息

在 Java 中,它将如下所示:

import com.google.api.ads.common.lib.auth.OfflineCredentials;
import com.google.api.ads.common.lib.auth.OfflineCredentials.Api;
import com.google.api.ads.common.lib.auth.OfflineCredentials.ForApiBuilder;
import com.google.api.ads.common.lib.exception.OAuthException;
import com.google.api.ads.common.lib.exception.ValidationException;
import com.google.api.client.auth.oauth2.Credential;

// ...

// Generate offline credentials
// With a previously created OAuth2 refresh token (see API examples)
ForApiBuilder forApiBuilder = new OfflineCredentials.Builder().forApi(Api.ADWORDS);
forApiBuilder.withClientSecrets(clientId, clientSecret);
forApiBuilder.withRefreshToken(refreshToken);

Credential credential = null;
try {
  credential = forApiBuilder.build().generateCredential();
} catch (OAuthException e) {
  throw new Exception("The given credential could not be refreshed: " + e.getMessage());
} catch (ValidationException e) {
  throw new Exception("Client ID, client secret or refresh token are not valid: " + e.getMessage());
}

// Build session
// ...

除了客户端 ID 和客户端密码之外,还需要将刷新令牌传递给凭据生成器。使用有效的 OfflineCredentials,您现在可以为特定 Google API.

构建新会话

关于你的第三个问题:请参阅以下question

的已接受答案

这里是源代码,显示了如何通过命令行为 Google AdWords(参见范围) 获取一次刷新令牌。客户端 ID 和客户端密码必须作为命令行参数传递。

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.PropertiesConfiguration;

import com.google.api.ads.common.lib.auth.GoogleClientSecretsBuilder;
import com.google.api.ads.common.lib.auth.GoogleClientSecretsBuilder.Api;
import com.google.api.ads.common.lib.auth.GoogleClientSecretsBuilder.GoogleClientSecretsForApiBuilder;
import com.google.api.ads.common.lib.exception.ValidationException;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.common.collect.Lists;

// ...

  private static final String SCOPE = "https://adwords.google.com/api/adwords";

  // This callback URL will allow you to copy the token from the success screen
  private static final String CALLBACK_URL = "urn:ietf:wg:oauth:2.0:oob";

  public static void main(String[] args) throws Exception {
    if (args.length != 2) {
      System.err.println("Please provide client ID and secret as commandline arguments!");
      System.err.println("If you do not have a client ID or secret, please create one in the API console: https://code.google.com/apis/console#access");
      System.exit(1);
    }

    GoogleClientSecrets clientSecrets = null;
    try {
      Configuration configuration = new PropertiesConfiguration();
      configuration.setProperty("api.adwords.clientId", args[0]);
      configuration.setProperty("api.adwords.clientSecret", args[1]);

      GoogleClientSecretsForApiBuilder googleClientSecretsForApiBuilder = new GoogleClientSecretsBuilder().forApi(Api.ADWORDS);
      googleClientSecretsForApiBuilder.from(configuration);

      clientSecrets = googleClientSecretsForApiBuilder.build();
    } catch (ValidationException e) {
      System.err.println("Invalid client ID or secret!");
      System.exit(1);
    }

    // Get the OAuth2 credential
    Credential credential = getOAuth2Credential(clientSecrets);

    System.out.printf("Your refresh token is: %s\n", credential.getRefreshToken());
    }
  }

  private static Credential getOAuth2Credential(GoogleClientSecrets clientSecrets) throws Exception {
    /*
     * Set the access type to offline so that the token can be refreshed. By
     * default, the library will automatically refresh tokens when it can, but
     * this can be turned off by setting api.adwords.refreshOAuth2Token=false
     */
    GoogleAuthorizationCodeFlow authorizationFlow = new GoogleAuthorizationCodeFlow.Builder(new NetHttpTransport(), new JacksonFactory(), clientSecrets, Lists.newArrayList(SCOPE)).setAccessType("offline").build();

    String authorizeUrl = authorizationFlow.newAuthorizationUrl().setRedirectUri(CALLBACK_URL).build();
    System.out.println("Paste this url in your browser: \n" + authorizeUrl + '\n');

    // Wait for the authorization code
    System.out.println("Type the code you received here: ");
    String authorizationCode = new BufferedReader(new InputStreamReader(System.in)).readLine();

    // Authorize the OAuth2 token
    GoogleAuthorizationCodeTokenRequest tokenRequest = authorizationFlow.newTokenRequest(authorizationCode);
    tokenRequest.setRedirectUri(CALLBACK_URL);
    GoogleTokenResponse tokenResponse = tokenRequest.execute();

    // Create the OAuth2 credential
    GoogleCredential credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport()).setJsonFactory(new JacksonFactory()).setClientSecrets(clientSecrets).build();

    // Set authorized credentials
    credential.setFromTokenResponse(tokenResponse);

    return credential;
  }

代码最初来自Goolge AdWords API example。我的版本没有从配置文件中读取,因为我不想将客户端 ID 和机密存储在某个资源文件中(我后来忘记删除了)。这就是将值作为参数传递给程序的原因。