I would like to list the logged user's files on Google Drive with my Spring Boot java application.
I have implemented the Google login flow, which works fine. I ask the user at login to permit access to his/her Google Drive. In a controller method, I access the idToken of the user. The intention is that I reuse this token and pass it to a Google Drive API call, but the API rejects this token. The API returns with the below error:
{
...
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
...
}
It looks like I cannot reuse this idToken. I guess, I will need another type of token, but cannot figure out, what kind of, and how. Can anyone advise?
Below is the controller method I used for testing:
@GetMapping("")
public ResponseEntity<List<String>> listFiles(Authentication authentication) throws IOException,
GeneralSecurityException {
// get idToken of authenticated user
OAuth2AuthenticationToken oauth2Auth = (OAuth2AuthenticationToken) authentication;
String idToken = ((DefaultOidcUser) oauth2Auth.getPrincipal()).getIdToken().getTokenValue();
Credentials credentials = IdTokenCredentials.create(AccessToken.newBuilder().setTokenValue(idToken).build());
// Build the Drive service and list files.
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);
}
You need to use Spring's OAuth2AuthorizedClientService to exchange the ID token for an access token.
private final OAuth2AuthorizedClientService clientService;
@GetMapping("")
public ResponseEntity<List<String>> listFiles(Authentication authentication) throws IOException,
GeneralSecurityException {
// get idToken of authenticated user
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
OAuth2AuthorizedClient client =
clientService.loadAuthorizedClient(
oauthToken.getAuthorizedClientRegistrationId(),
oauthToken.getName());
String accessToken = client.getAccessToken().getTokenValue();
Credentials credentials = IdTokenCredentials.create(AccessToken.newBuilder().setTokenValue(accessToken).build());
// Build the Drive service and list files.
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);
}