Welcome to Part 6 of this series of guides on how to integrate Gmail with Angular and Spring Boot.

Thus far, all you've done is made some progress with OAuth2 authentication. You haven't actually used the Gmail API yet.

Be patient. You're getting there.

In this guide, you'll get the access token and the refresh token. You'll do that with the aid of the authorization code you got in the previous guide.

If you prefer to skip the required reading, you can just go grab the code from GitHub.

Otherwise, stay awhile.

You've Come a Long Way, Baby

Up to this point, you have:

  • Created an OAuth2 client ID and secret on Google Cloud Console
  • Enabled the Gmail API via Google Cloud Console
  • Set the necessary properties in your Spring Boot application.properties file 
  • Set up a DataStore implementation with its associated factory
  • Set up a refresh listener
  • Created a utility class that handles the Google authorization code flow
  • Set up proper Gmail consent with the Google Cloud Platform
  • Created a controller that handles a request to get the Google authorization code flow URL
  • Used Postman to get the Google authorization code URL
  • Used that URL to authorize your application to access your Gmail inbox

And if you haven't done those things, I suggest you check out Part 1 and work forward from there.

You're Going a Longer Way

In this guide, you will:

  • Update the controller so it handles a token request
  • Update the utility class so it creates the credential from the token
  • Use Postman to retrieve the access token

And the good news is: at the end of this guide, you're done with OAuth2 work. 

In the next guide, you'll tackle Gmail integration.

Controller Freak

Start by updating GmailController. You'll need to add a new method.

    @PostMapping("/email/token")
    public ResponseEntity<?> createToken(@RequestBody GoogleAuthResponse auth) {
        LOG.debug("In createToken " + auth);

        User currentUser = authUtil.getCurrentUser();
        
        try {
            Credential credential = googleOauthUtil.getCredentialFromCode(auth, currentUser.getId());           
            return ResponseEntity.ok(credential.getAccessToken());
        } catch (Exception e) {
            LOG.error("Problem retrieving credential!", e);
        }
        
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Problem creating token!");
    }   

That method listens for a POST request at the email/token endpoint. The request body maps to the GoogleAuthResponse object.

That's a plain old Java object (POJO) that includes only two properties: code and redirectUrl.

The code property holds the Google authorization code that you got in the previous guide. The redirectUrl property is where the application will take the user once it delivers the token.

As with the previous method, the code instantiates a User object based on the contents of the Bearer token used to access the endpoint. It does that with the assistance of the AuthorizationUtil class. 

Then, it uses GoogleOauthUtil to generate the access token and return it to the user.

Please do not confuse Bearer token and access token. They're two different things.

The Bearer token is what you send to the email service to demonstrate that you're authorized to access the endpoint.

The access token is what you'll receive in response. The application will use that token to demonstrate that it's authorized to access your Gmail inbox.

Next, let's take a look at GoogleOauthUtil.

Revisiting the Utility Belt

Here's the GoogleOauthUtil method that the controller uses to collect the token:

	public Credential getCredentialFromCode(GoogleAuthResponse auth, String id) {		
        Credential credential = null;

	    try {
		    GoogleAuthorizationCodeFlow acf = getAuthorizationCodeFlow(id);
		        
	        AuthorizationCodeTokenRequest req = acf.newTokenRequest(auth.getCode());
	        req.setRedirectUri(auth.getRedirectUrl());

			TokenResponse response = req.execute();
			LOG.debug(response.toPrettyString());
			
			credential = acf.createAndStoreCredential(response, id);
		} catch (Exception e ) {
			LOG.error("Problem creating credential!", e);
		}
		
		return credential;
	}

The method gets the ball rolling by instantiating a GoogleAuthorizationCodeFlow object. I explained how the getAuthorizationCodeFlow() method works back in Part 3. So I won't rehash it here.

But this time the GoogleAuthorizationCodeFlow object is doing something different. Instead of returning a URL, it's returning an instance of AuthorizationCodeTokenRequest.

That's the object that handles an OAuth2 request for an access token.

Next, the code sets the redirect URL as specified in the GoogleAuthResponse object. 

Then, the code invokes the execute() method on the AuthorizationCodeTokenRequest object. That's going to return an instance of TokenResponse.

After that, the code invokes the createAndStoreCredential() method on the GoogleAuthorizationCodeFlow object. That method will not only create the credential, it will also persist it as the googleApi property in the MongoDB user document.

Finally, the method returns the Credential object to the controller.

The controller will get the access token from that Credential object and return it to the client.

Now it's time for another test.

Back to Postman

When we last parted company, you had used Postman to generate an authorization code. Now you'll use that authorization code to get the token.

As it stands now, you're staring at a URL in your browser that looks like this:

http://localhost:4200/?code=4/0AY0e-g5WD-ddddddddOF1KwS5vsjQ&scope=https://mail.google.com/

Hang on to that URL and go back to Postman. Create a new request:

 

For starters, note the endpoint: http://localhost:32050/email/token. Unless you've changed the default configuration, that's the URL you need to use.

Also, note the method: POST

And then take a look at the body. It's a JSON payload.

That "code" property needs to match the code request parameter in the URL you got back from Google. So everything between "code=" and the ampersand is the value of the "code" property in the JSON object.

You might have to look for an escaped character in the URL. If you see 4%2F instead of 4/ at the beginning, just substitute a / for the %2F.

Next, just dummy up "redirectUrl" for now to http://localhost:4200

And don't forget to set the Bearer token in the Authorization tab!

 

Once you're all set up, click that blue Send button. The response will look something like this:

ba49.a0AfdddddddddddddddddddddddddddddddddddddddddddddV9_syXVnkdu_Pu8c50phEbC8sSZF4JFd768uogZJ9ZJL

That's your access token.

But you don't need it.

No, really. You don't need it.

If you've been paying careful attention through all these guides, then you already know why you don't need it.

In fact, the controller just returns the token as a formality for now. It's something you can take a look at later on.

If you're not sure why you don't need the token, you'll have to wait until the next guide when I explain it.

Wrapping It Up

So I'll leave this one with a tease.

Remember: if you're struggling because everything doesn't work for you exactly as you see it here, you might have to do some digging to find out what's wrong. Search engines can be your best friends in those types of cases.

But if the happy path worked for you, you're well on your way to Gmail integration.

Have fun!

Photo by Karolina Grabowska from Pexels