Spring Boot调用Google Drive API:idToken无效问题求助
问题:Spring Boot调用Google Drive API时idToken验证失败
我通过Spring Boot Java应用实现了Google登录流程,登录时已请求用户授权访问其Google Drive,但用用户的idToken调用Drive API时被拒绝,错误提示:
Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential.
不清楚应该使用哪种token,以及如何获取,附上测试用的控制器代码:
@GetMapping("") public ResponseEntity<List<String>> listFiles(Authentication authentication) throws IOException, GeneralSecurityException { // 获取已认证用户的idToken OAuth2AuthenticationToken oauth2Auth = (OAuth2AuthenticationToken) authentication; String idToken = ((DefaultOidcUser) oauth2Auth.getPrincipal()).getIdToken().getTokenValue(); Credentials credentials = IdTokenCredentials.create(AccessToken.newBuilder().setTokenValue(idToken).build()); // 构建Drive服务并列出文件 Drive service = new Drive.Builder(GoogleNetHttpTransport.newTrustedTransport(), new GsonFactory(), new HttpCredentialsAdapter(credentials)).setApplicationName(APPLICATION_NAME) .build(); FileList result = service.files().list().setPageSize(10).setFields("files(name)").execute(); List<String> fileNames = result.getFiles().stream().map(file -> file.getName()).toList(); return ResponseEntity.ok(fileNames); }
解决方案
核心原因
idToken的作用是身份认证,仅用于验证用户身份,无法用来访问Google资源类API(比如Drive)。访问这类API必须使用OAuth2 Access Token,它才是用户授权后,允许应用访问其资源的凭证。
获取Access Token的方法
在Spring Security OAuth2登录流程中,用户完成授权后,OAuth2AuthenticationToken对象中已经包含了Access Token:
- 直接通过
oauth2Auth.getAccessToken()获取OAuth2AccessToken对象,从中提取token值和过期时间。 - 若Spring Security版本较低,也可以从
DefaultOidcUser的属性中提取:oidcUser.getAttributes().get("access_token")
修改后的控制器代码
@GetMapping("") public ResponseEntity<List<String>> listFiles(Authentication authentication) throws IOException, GeneralSecurityException { OAuth2AuthenticationToken oauth2Auth = (OAuth2AuthenticationToken) authentication; // 获取Access Token OAuth2AccessToken accessToken = oauth2Auth.getAccessToken(); String accessTokenValue = accessToken.getTokenValue(); // 用Access Token创建合法凭证 Credentials credentials = GoogleCredentials.create( new AccessToken(accessTokenValue, accessToken.getExpiresAt()) ); // 构建Drive服务并调用API Drive service = new Drive.Builder(GoogleNetHttpTransport.newTrustedTransport(), new GsonFactory(), new HttpCredentialsAdapter(credentials)) .setApplicationName(APPLICATION_NAME) .build(); FileList result = service.files().list() .setPageSize(10) .setFields("files(name)") .execute(); List<String> fileNames = result.getFiles().stream() .map(com.google.api.services.drive.model.File::getName) .toList(); return ResponseEntity.ok(fileNames); }
额外注意事项
- 确保Google Cloud控制台的OAuth2客户端配置中,已添加Drive API的授权范围(例如
https://www.googleapis.com/auth/drive.readonly),且用户登录时应用确实请求了这些范围。 - 如果使用低版本Spring Security,
OAuth2AuthenticationToken.getAccessToken()不可用,可改用属性提取方式,同时需手动处理token过期逻辑。
内容的提问来源于stack exchange,提问作者SaWo
相关产品推荐
相关产品推荐

