GoogleMail:使用 OAuth 2.0 刷新访问令牌

GoogleMail: Refresh Access Token with OAuth 2.0

我有以下方法来获取 Google 邮件凭据。然而,访问令牌是短暂的,并在 24 小时后过期。如何刷新?

我的方法:

 private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
        // Load client secrets.
        InputStream in = GoogleMail.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
        if (in == null) {
            throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
        }
        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(GSON_FACTORY, new InputStreamReader(in));

        // Build flow and trigger user authorization request.
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
                HTTP_TRANSPORT, GSON_FACTORY, clientSecrets, SCOPES)
                .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
                .setAccessType("offline")
                .setApprovalPrompt("force")
                .build();
        LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
        return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
    }

我看到了令牌刷新方法,但如何将其与我的方法 (getCredentials) 结合使用?

public Credential refreshAccessToken(String refreshToken, String clientId, String clientSecret) throws IOException {
try {
  TokenResponse response =
  new GoogleRefreshTokenRequest(new NetHttpTransport(), new JacksonFactory(),
      refreshToken, clientId, clientSecret).execute();
  System.out.println("Access token: " + response.getAccessToken());
  return buildEmpty().setAccessToken(response.getAccessToken());
} catch (TokenResponseException e) {
  if (e.getDetails() != null) {
    System.err.println("Error: " + e.getDetails().getError());
    if (e.getDetails().getErrorDescription() != null) {
      System.err.println(e.getDetails().getErrorDescription());
    }
    if (e.getDetails().getErrorUri() != null) {
      System.err.println(e.getDetails().getErrorUri());
    }
  } else {
    System.err.println(e.getMessage());
  }
}

实际上访问令牌会在一小时内过期,而不是 24 小时。您不需要刷新客户端库专为您设计的访问令牌。

如果您关注 Java quickstart

注意它是如何使用名为 TOKENS_DIRECTORY_PATH 的东西的。当用户第一次授权该应用程序时,他们将被要求同意您的应用程序访问。如果用户授予您的应用程序访问权限,那么访问令牌和刷新令牌将返回到您的应用程序并作为文件存储在此 TOKENS_DIRECTORY_PATH.

// Build flow and trigger user authorization request.
    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
            HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
            .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
            .setAccessType("offline")
            .build();

在示例的更下方,您会发现这一行

return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");

这会告诉客户端库代表名为“user”的用户授权应用程序。然后库所做的是在 TOKENS_DIRECTORY_PATH 中查找名称中包含“用户”的文件,如果该文件不存在,则会弹出同意屏幕并请求访问权限。如果它确实存在,那么库将从文件中读取刷新令牌并为您刷新访问令牌。

如果您的代码配置正确,您不必担心刷新访问令牌,客户端库将为您处理所有这些。

根据 documentation of the Credential class,您在创建凭据时应该这样做:

public static Credential createCredentialWithRefreshToken(
    HttpTransport transport, 
    JsonFactory jsonFactory, 
    TokenResponse tokenResponse) {
    return new Credential.Builder(BearerToken.authorizationHeaderAccessMethod())
       .setTransport(transport)
       .setJsonFactory(jsonFactory)
       .setTokenServerUrl(new GenericUrl("https://server.example.com/token"))
       .setClientAuthentication(new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"))
       .build()
       .setFromTokenResponse(tokenResponse);
 }