OAuth 2.0访问令牌和刷新令牌

时间:2015-02-02 07:24:02

标签: google-oauth access-token

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

我的问题是,

  1. 在这里传递googleCredential对象时,我是否需要处理刷新令牌? (假设脚本运行超过一天)
  2. 什么时候应该使用刷新令牌和访问令牌,在上面的用例中,对我来说什么是正确的选择? (虽然目前我没有明确传递除googleCredential对象之外的任何内容)
  3. 访问令牌和刷新令牌的有效时间是什么(与上述用例无关,只是要知道,有些人说刷新令牌有14天,有人说无限期直到用户撤销访问权限等)
  4. 如果有人澄清我并把我拉出来,我会很满意的。我知道这个平台主要是为了澄清代码问题,但谷歌论坛也没有帮助。所以发帖在这里。

    抱歉非常详细。

    提前致谢。

1 个答案:

答案 0 :(得分:7)

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

请查看Using OAuth 2.0 to Access Google APIs

  
      
  1. 如有必要,请刷新访问令牌。
  2.         

    访问令牌的生命周期有限。如果您的应用需要在单个访问令牌的生命周期之后访问Google API,则可以获取刷新令牌。刷新令牌允许您的应用程序获取新的访问令牌。

         

    注意:在安全的长期存储中保存刷新令牌,只要它们仍然有效,就继续使用它们。限制适用于每个客户端 - 用户组合以及所有客户端中的每个用户发布的刷新令牌的数量,并且这些限制是不同的。如果您的应用程序请求足够的刷新令牌超过其中一个限制,则较旧的刷新令牌将停止工作。

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和密码存储在某个资源文件中(我以后忘记删除)。这就是为什么值作为参数传递给程序。