Spring Boot: Saving OAuth2 login data in DB using PrincipalExtractor

This post is a continuation of configuring OAuth2 login in Spring Boot. If you want to know how to configure the login itself, please take a look at the previous post.

As I mentioned previously, we want to save user login data in our database to be able to connect matches data with their users. We’re going to save only some basic data – the external id of the user from the provider to distinguish the user, her full name (that I want the user to be able to replace it with the nickname in the future), avatar and e-mail address. Let’s start with the database. As we already configured Liquibase, we are able to add a migration that will create the table in the DB:

As we have only one provider now, we could as well skip the login_type column. That would mean that if we add a new provider, we’d likely need to add this column and prepare migration that adds the value for existing records, so I decided that it’s a good idea to start with it. When we now start the application, the table is created in the database:

Next step is adding User entity class and its related Repository interface we’ll be using for DB access. As I wanted to use LocalDateTime for managing dates, but JPA doesn’t work that well with it yet, I needed to add Jsr310JpaConverters class to @Entityscan in my MatchloggerApplication class.

The last part was using PrincipalExtractor to obtain the data we want, actually save them into the database and mark that they will be used as principal data. The documentation of this class is virtually non-existent, but I found this example. I added a similar section to my WebSecurityConfiguration.java with just returning the same I received to check which data I am able to obtain.

That was the set of data provided by PrincipalExtractor. It appears that everything that I wanted to get is available here, but there is one potential issue I may come up with in future – as long as I have only one authentication provider, I know that those data come from Google, but if I have several providers and they provide different data, it might be the case that I’ll need to find out the provider based on some keys’ existence. Not the best option, but seems I need to stick with it for now (if anybody knows a better option, please let me know).

My WebSecurityConfiguration class looks like this now:

After adding the PrincipalExtractor, I am able to see that on successful login I have my first user in the database.

Let’s then modify the code that returns user data to use my new configuration:

After login, this is a current message that we see:

One note to add is that Java 8 LocalDateTime doesn’t look too nice in generated JSON response. I’ll likely convert the returned value into a timestamp in the future, depending on view layer’s needs.