Access google drive data with Spring Boot

Syed Hasan
6 min readNov 21, 2020

In this article I will explain how we can access to google drive data with any server side java application (I have demonstrated with Spring boot). The resource for accessing google APIs are not that available throughout the internet, therefore I was requested to write an article on it.

Works in google developer console

Now we need to create an app in google developer console and configure the necessary things.

Create App

Open your browser and go to https://console.developers.google.com/ and create an app. I have named my app as google-drive-demo.

Once you have created your app, you will be redirected to APIs & Services page. Click on Enable APIs and Services button.

Search for drive and select the Google Drive API.

Now enable the Google Drive API from the next screen.

Now that you have enabled the API, you have to create credentials for your app. Click on the CREATE CREDENTIALS button on top left corner.

Fill in the form with required information and click on What Credentials Do I Need? button.

Click on Done.

Now you have to configure your consent screen before you can create your credentials. Click on the CONFIGURE CONSENT SCREEN button on the top right corner.

Select User Type External and click on Create.

Provide the app name, User Support Email and Developer Contact Information.

Clicking on Save and Continue button will take you to the scopes configuration screen. Click on ADD OR REMOVE SCOPES.

Select the required scopes and click on Update. Once you have your scopes on the Scopes screen, click on SAVE AND CONTINUE.

You can add some test users who can be able to access the consent screen to use their google drive. For demonstration purpose I am adding only one.

Click on SAVE AND CONTINUE. Once you are done here, go to Credentials page and add credentials. Click on CREATE CREDENTIALS and then select OAuth Client ID.

Provide the required information and click on CREATE

Note that the Authorized Redirect URLs will be used by google to redirect the user to his application when he will provide the consent from consent screen. We will need to create an endpoint in our spring boot application so that we can receive the redirection hit from google’s authorization server.

Once we have done these successfully, we have received a Cliend ID and Client Secret from google. We need to put them these client credentials and the scopes in our spring boot application’s application.properties file for further use.

Note that the scopes are not only the endpoints but the full URLs.

Dependencies

Along with other dependencies, we specially need spring-boot-starter-oauth2-client dependency.

implementation "org.springframework.boot:spring-boot-starter-oauth2-client:3.1.0"

This dependency will be used as a client to connect to google oauth server.

Connecting to google OAuth Server

Security Configuration

Our OAuth Security Configuration will require 2 beans for this purpose.

  1. ClientRegistrationRepository Bean
  2. OAuth2AuthorizedClientService Bean

These beans have been defined in Beans.java file. You will find them in the project repository.

The rest of the security configuration are not much different, which will be found in SecurityConfig.java file.

Defining Callback Controller

I mentioned earlier, google will look for a callback url in our application to redirect user. In controllers package, go to GoogleAuthRedirectController class, there you will find a method with following request mapping.

/oauth2/callback/google

The code of the controller method is below.

@RequestMapping("/oauth2/callback/google")
public String callbackUrl(
HttpServletRequest request,
HttpSession httpSession) {
String code = request.getParameter("code");
String accessDenied = request.getParameter("access_denied") == null
? "" : request.getParameter("access_denied");
if (!accessDenied.isBlank()) throw new CalendarAccessDeniedException("Authorization from google failed");
String error = request.getParameter("error") == null
? "" : request.getParameter("error");
if (!error.isBlank()) throw new CalendarAccessDeniedException("Authorization from google failed");
String[] scopes = request.getParameter("scope").split(" ");
if (code.isBlank()) throw new CalendarAccessDeniedException("Authorization from google failed");
String scopeWithCalendarPermission =
Stream.of(scopes)
.filter(s -> s.contains("drive"))
.findFirst()
.orElseThrow(() -> new CalendarAccessDeniedException("You must have to allow calendar data to be accessed."));
httpSession
.setAttribute(SessionKey.GOOGLE_OAUTH_TOKEN.toString(),
oauthTokenService.fetchToken(code, scopeWithCalendarPermission)
);
return "redirect:/files";
}

Google will send at least authorization_code and scopes to this endpoint for a successful authorization. So this is going to be OAuth2 Authorization code flow. If you are unfamiliar with this term, you can check out this article.

Getting access token from google by using authorization_code

We have the authorization code but for accessing resources we need an access token. If you look closely into our callback controller method, you will see, it has called a method fetchToken(…) which is defined in OAuthTokenService class.

Peek into fetchToken(…) method. You will see, there is a REST call to https://accounts.google.com/o/oauth2/token.

public String fetchToken(String code, String scope) {
final String uri = "https://accounts.google.com/o/oauth2/token";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
String clientCredentials = Base64.getEncoder().encodeToString((CLIENT_ID+":"+CLIENT_SECRET).getBytes());
headers.add("Authorization", "Basic "+clientCredentials);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("code", code);
requestBody.add("grant_type", "authorization_code");
requestBody.add("redirect_uri", "http://localhost:8080/oauth2/callback/google");
requestBody.add("scope", scope);

HttpEntity<MultiValueMap<String, String>> formEntity = new HttpEntity<>(requestBody, headers);

ResponseEntity<OauthResponse> response = restTemplate.exchange(uri, HttpMethod.POST, formEntity, OauthResponse.class);
return response.getBody().getAccess_token();
}

For making a simple demonstration, I will call the API for fetching all files. The code for getting all files will be found in GoogleDriveService#getDriveFiles(…) method.

public DriveFiles getDriveFiles(String accessToken) {
String requestUri = "https://www.googleapis.com/drive/v3/files";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Authorization", "Bearer " + accessToken);

HttpEntity request = new HttpEntity(headers);
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
new MappingJackson2HttpMessageConverter();
restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
ResponseEntity<String> response = restTemplate.exchange(requestUri, HttpMethod.GET, request, String.class);

Gson gson = new Gson();
DriveFiles driveFiles = gson.fromJson(response.getBody(), DriveFiles.class);

return driveFiles;
}

To get the API Documentation you can visit Google Drive API Reference.

Demonstration

Start the application and navigate to

http://localhost:8080/

You will see almost an empty page but containing Login with Google.

Click on the link. You will be redirected to the Google Login Screen.

If you can remember, I only added the Team G5 account for test user while configuring the 3rd step of consent screen. So I will select the Team G5 account from this screen. Selecting any other account will show me an error with code 403.

Once I have provided the consent, I will be able to see my file IDs and Names.

Wrapping Up

To get the complete source code, visit the branch

poc/google-drive-demo/complete

of this github link.

--

--

Syed Hasan

Software Engineer | Back-End Developer | Spring Developer | Cloud Enthusiast