Using a DB and JPA as Data Store for Google Authentication
Hello there,
I was tasked with doing an integration to one of the Google APIs from my Groovy code. The first question that naturally arises is authentication and authorization, how to access the API, mainly because you can not even see anything useful as clients until you authenticate. As I go deep into the Google documentation I fear more and I shiver thinking who was the main audience for this documentation? Because in that moment it did not feel for me. But I overcame this dramatic instant when I got down to work and figured out how to use JPA as datastore to store user credentials in my app. Eventually I realized that using Service accounts was better for what was wanted, however since I didn’t find a lot of stuff out there about a JPA store I thought this might be useful for one of you integrating Google OAuth into your Spring project. The code was tested on Spring boot v2.2.6 and Groovy v3.0.4. The underlying DB is MySQL but that shouldn’t be very relevant for the code at hand as long as you are using JPA since I’m not doing any queries outside of common Spring Data finders.
Now let me tell what this blog post won’t help you with: understanding how OAuth2 works, Google authentication flows and how to authenticate to a particular Google API you are working with, all that info is out there:
Having the backstory out the way, let’s jump to the code.
To authenticate against Google with OAuth2 I used the Google Auth Java library. The library does some things for you and your job is to implement the Google Authorization flow for which you need to pass a DataStore and a DataStoreFactory to store your Google OAuth credentials (incidentally called StoredCredential
). Per the library documentation a datastore is necessary because:
Most applications will need to persist the credential’s access token and/or refresh token. To persist the credential’s access and/or refresh tokens, you can provide your own implementation of DataStoreFactory with StoredCredential; or you can use one of the following implementations provided by the library:
AppEngineDataStoreFactory: persists the credential using the Google App Engine Data Store API.
MemoryDataStoreFactory: “persists” the credential in memory, which is only useful as a short-term storage for the lifetime of the process.
FileDataStoreFactory: persists the credential in a file.
None of these were relevant for my use case, so I went hunting for an implementation with a DB as a store. I found this post, that was a little outdated for the versions I’m using, but it was very useful to understand what interfaces I needed to implement from the library.
I’m using Gradle as build system version 6.2.2 and these dependencies:
Let’s start with the entity definition where the credentials will be stored:
And the repository:
The DataStoreFactory is relatively simple, note that it’s making use of DbDataStore that is defined below.
And the DataStore implementation:
Finally we can use our data store definition to pass it to the authentication flow. This code is to authenticate against Google’s DFA and Trafficking API, it should be translatable to other Google APIs:
And that’s about it, you have a DB Data Store for your Google Credentials in Spring using JPA and a DB to cache the credentials details.
May your DBStores work in you framework of choice. Stay safe out there!