多次调用graphClient报OAuth2授权码已兑换错误如何解决
报错原因
该报错由OAuth2授权码的一次性特性导致:授权码是仅可使用一次的临时凭证,只能兑换一次访问令牌(access token)和刷新令牌(refresh token)。首次调用Graph接口时,SDK已经用传入的授权码完成了凭证兑换,第二次调用时如果无法复用已有的访问令牌,SDK会尝试复用授权码再次兑换,进而触发AADSTS54005错误。
触发该场景的具体诱因有两个:
- 权限配置不全:当前代码仅配置了
mail.read权限,调用getUserDetails()需要User.Read权限,调用getUserGroups()需要GroupMember.Read.All或Directory.Read.All权限,权限不匹配导致首次兑换的令牌无法满足第二个接口的校验要求,SDK只能尝试重新兑换令牌。 - 缓存逻辑未生效:如果
initializeGraphAuth方法被重复调用,或者graphClient实例被重复创建,首次兑换的令牌缓存会丢失,也会导致SDK重新使用授权码兑换。
修复方案
1. 补全权限列表
修改initializeGraphAuth方法的scopes配置,添加所有需要用到的接口权限:
public static void initializeGraphAuth(String authorizationCode) { List<String> scopes = new ArrayList<>(); scopes.add("https://graph.microsoft.com/mail.read"); // 新增用户信息读取权限 scopes.add("https://graph.microsoft.com/User.Read"); // 新增用户组成员关系读取权限 scopes.add("https://graph.microsoft.com/GroupMember.Read.All"); // 原有逻辑保持不变 final AuthorizationCodeCredential authCodeCredential = new AuthorizationCodeCredentialBuilder().clientId(AzureConstants.CLIENT_ID).clientSecret(AzureConstants.CLIENT_SECRET).authorizationCode(authorizationCode).redirectUrl(AzureConstants.REDIRECT_URI).build(); authProvider = new TokenCredentialAuthProvider(scopes, authCodeCredential); DefaultLogger logger = new DefaultLogger(); logger.setLoggingLevel(LoggerLevel.ERROR); graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).logger(logger).buildClient(); }
2. 保证graphClient单例
确保initializeGraphAuth方法在应用的生命周期内仅被调用一次,不要重复初始化graphClient实例。AuthorizationCodeCredential内置的内存缓存会自动复用已获取的访问令牌,令牌过期后也会自动用刷新令牌兑换新的访问令牌,不会重复使用原始授权码。
3. 可选优化:合并请求
如果需要同时获取用户信息和用户组信息,可以使用Graph API的批处理能力,将两次请求合并为一次调用,进一步降低令牌兑换的触发概率,提升接口调用效率。
修改完成后,先确认Azure AD应用注册中已经为上述权限授予了管理员同意或用户同意,再同时调用两个方法即可正常获取结果。
内容的提问来源于stack exchange,提问作者Mahesh
相关产品推荐
相关产品推荐

