java - Microsoft Graph 和 Java - 针对授权代码流的多次调用
问题描述
几个小时以来,我一直在尝试解决这个问题,现在我在兜圈子,浪费了有趣的 RnD 时间。我正在使用 MS Graph API 来访问 Office 365,并且我已经使用授权流程对其进行了设置,以授权我的 Java servlet。它工作正常(获取身份验证代码的 URL 在其他地方)但我只能运行一个调用。我在后续调用的异常中收到以下错误(在我的代码中,是在我尝试查看驱动器时):
OAuth2 授权代码已被兑换,请使用新的有效代码重试或使用现有的刷新令牌。
我假设这意味着我需要刷新我的令牌(真的很明显,而且我发现关于这个的注释说现在在这个流程中是必要的),但我不知道如何使用 GraphServiceClient .
我的代码在下面,在我将笔记本电脑从最近的窗口飞出之前,任何帮助都将受到欢迎。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
String code = request.getParameter("code");
String clientId = "***";
String clientSecret = "***";
String authorisationCode = code;
String redirectURL = "http://localhost:8080/O365Web/auth";
String tenant = "***";
AuthorizationCodeCredential authCodeCredential = new AuthorizationCodeCredentialBuilder()
.clientId(clientId)
.clientSecret(clientSecret) //required for web apps, do not set for native apps
.authorizationCode(authorisationCode)
.redirectUrl(redirectURL)
.build();
List<String> scopes = new ArrayList<String>();
scopes.add("https://graph.microsoft.com/User.Read");
scopes.add("https://graph.microsoft.com/Files.ReadWrite.All");
scopes.add("https://graph.microsoft.com/offline_access");
TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(scopes, authCodeCredential);
GraphServiceClient graphClient =
GraphServiceClient
.builder()
.authenticationProvider(tokenCredentialAuthProvider)
.buildClient();
try {
final User me = graphClient.me().buildRequest().get();
out.println("Name: " + me.displayName + "");
} catch ( Exception ex ) {
out.println("Exception in first user get: " + ex.getMessage() );
ex.printStackTrace();
}
try {
DriveItemCollectionPage children = graphClient.me().drive().root().children().buildRequest().get();
while ( children != null ) {
for ( DriveItem item : children.getCurrentPage() ) {
out.println("C:" + item.name + " : " + item.id);
}
DriveItemCollectionRequestBuilder builder = children.getNextPage();
if ( builder != null ) {
out.println("Loading page...");
children = children.getNextPage().buildRequest().get();
} else {
children = null;
}
}
} catch ( Exception ex ) {
out.println("Exception in children get: " + ex.getMessage());
ex.printStackTrace();
}
try {
final User me2 = graphClient.me().buildRequest().get();
out.println(me2.displayName + "<br/>");
} catch ( Exception ex ) {
out.println("Exception in second user get: " + ex.getMessage());
ex.printStackTrace();
}
}
解决方案
我已经在我的环境中测试过了。
当我首先运行请求时,我能够生成访问令牌
当我再次运行相同的请求时,我也得到了同样的错误:
OAuth2 授权码已兑换,请使用新的有效代码重试或使用现有的刷新令牌
错误原因是authCodeCredential中使用的授权码只能使用一次
String authorisationCode = code;
如果要发出新请求,可以生成新的授权码(获取授权码的 URL 在别处)并在 authCodeCredential 中使用
这可以解决问题
另一种方法是使用刷新令牌。
使用 URL 生成授权代码时,您可以使用offline_access添加另一个范围
现在,在使用授权代码生成访问令牌时,使用offline_access添加另一个范围。这将生成一个刷新令牌和访问令牌。
现在,您可以在访问令牌过期时使用刷新令牌生成新的访问令牌
推荐阅读
- vue.js - 是否可以更改 vue 的网格系统尺寸?
- python - 使用 lambda 和 defaultdict 定义 Trie 树
- javascript - 输入正确密码后,如何停止再次显示密码提示?
- python - Python/Discord 当我尝试让 python 获取不和谐用户的用户 ID 时,它什么也不做,没有错误消息,也没有输出
- c# - C# asp web 表单 - 如何确保 Response.Flush() 内容输出首先被客户端接收然后只执行下一条语句?
- scala - 为什么 Scala API 文档缺少类?
- python - Python:编写嵌套 for 循环和 if 语句的更好方法
- regex - 选择多个多行字符串
- r - R函数用单词向量过滤句子向量
- vb.net - 如果在 Vb 中选择了六个复选框中的任何三个复选框,是否有任何推荐的代码在单独的标签中显示特定值?