java - 在 Java 中使用 Oauth2 的 Gmail 以及带有 AuthorizationCodeFlow 的刷新令牌
问题描述
我有一个自动邮件系统,它有一组配置的 Gmail 帐户。Google 强制用户使用 Oauth 发送邮件,所以我从Google API Console创建了一个新的 Client ID 和 Client Secrete 。我已经授权 Gmail 使用Python 脚本访问我的帐户,所以我已经有了一个刷新令牌。
我的问题是我正在尝试使用带有刷新令牌的AuthorizationCodeFlow获取新的访问令牌,但我得到了空值:
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.auth.oauth2.TokenResponse;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeRequestUrl;
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.GoogleTokenResponse;
import com.google.api.client.http.BasicAuthentication;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.util.store.MemoryDataStoreFactory;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
public class Main {
public static void main(String[] args) throws IOException {
String clientId = "748679640358-....b.apps.googleusercontent.com";
String clientSecret = "tUI4ggLLexNc...MRM";
String refreshToken = "1//0...........ARAAGBESNwF-L9Ir988VdRV3oiTYOQwygPjmwKw5r9Bi82q7JuoF2CysWw6xzW3z3Tda18GU5A_JMgdkGKw";
List<String> scopes = Arrays.asList("https://mail.google.com/");
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
// Sends requests to the OAuth server
new NetHttpTransport(),
// Converts between JSON and Java
JacksonFactory.getDefaultInstance(),
// Your OAuth client ID
clientId,
// Your OAuth client secret
clientSecret,
// Tells the user what permissions they're giving you
scopes)
// Stores the user's credential in memory
.setDataStoreFactory(MemoryDataStoreFactory.getDefaultInstance()).build();
Credential credential;
try {
credential = flow.loadCredential(clientId);
} catch (IOException e) {
// Error getting login status
credential = null;
}
if (credential == null) {
TokenResponse tokenResponse = new TokenResponse().setRefreshToken(refreshToken);
credential = flow.createAndStoreCredential(tokenResponse, clientId);
}
String accessToken = credential.getAccessToken();
System.out.println(accessToken); // THIS PRINTS null
}
}
我不知道我错过了什么,任何帮助都会非常感激
解决方案
与使用 Java 或 Google 开发的任何工具一样,存在许多极其重要的缺失信息。有一个refreshToken方法(当然在任何教程和文档中都没有提到),它成功了:
...
if (credential == null) {
TokenResponse tokenResponse = new TokenResponse().setRefreshToken(refreshToken);
credential = flow.createAndStoreCredential(tokenResponse, clientId);
credential.refreshToken();
}
...
我希望它可以防止有人浪费几天时间来使事情顺利进行
推荐阅读
- python - 如何从 JSON Lambda 输出中提取一个值?
- c# - ClassVar.prefab 未显示在 Unity 的检查器中
- .net - 如何使用 Azure AD 对 Azure .net API 调用进行身份验证?
- typescript - TypeScript 说尽管我尝试严格定义我的道具,但道具类型是未知的
- android - 用于导入 android.annotation.CallSuper 的 activity.java 中的错误
- asp.net-core - IdentityServer 前端显示缺少结构
- java - 如何设置仅在 android 中首次启动时出现的活动?
- python - 用户未添加成员
- c# - 使用复选框创建 WPF Windows 资源管理器树视图
- r - 如何使这些树状图分支看起来整洁清晰?