Spring Security 5.3 OAuth2 integration with Facebook along with Form-Based login

Rajeev Shukla
7 min readMay 1, 2020

--

Introduction

OAuth2 configurations are quite intimidating. You might have come across to see many people have tried to simplify by writing blogs, series about how to integrate OAuth2 facebook with Spring security in many different ways but when we start we get stuck as it does not work because of so many different configurations. Also, you don’t understand where to make changes to customize it according to your project.

In this post, we are going to see the simplest way of spring security 5 Facebook oauth2 integration along with form-based where users can either log in via Facebook or by entering username password in the login form.

In this post implementation is going to in-memory only. The whole idea is to show the minimal configuration of spring security 5 for OAuth2 integration with Facebook along with form-based authentication. I have a plan to take it to the next level using DB and email integration and remember me blah blah. So stay tuned for the next post!!!

Adding Dependency

With the assumption that you have knowledge on how to create spring boot project and have an understanding of the basics of maven, spring MVC following is the dependency, you need to add in your pom.xml.

  • The latest spring security project provides support for the OAuth2 server dependency but not the client. Since we need to connect to the Facebook OAuth server as a client so we need to add ‘oauth2-client’ dependency.

For experts who know the internals of spring security, OAuth2-client dependency is needed along with spring security because spring security needs OAuth2LoginAuthenticationFilter in its filter chain to be present on classpath in order to support OAuth client Integration. Which is present inside spring-boot-starter-oauth2-client. We will cover this later in upcoming posts.

  • Adding tomcat-embed-jasper dependency in order to support spring-MVC with JSP.

Project Structure

Hint: To support JSP you need to have webapp as a source folder and create WEB-INF/jsp/ under it. In eclipse you can Right-click on project>new>source folder and name it webapp. And then create two folders WEB-INF/jsp/.

Creating a Facebook App for Oauth 2 Login

  • Go to https://developers.facebook.com/
  • Login and create a new app
  • Add details like application name, URL, and any required details.
  • After successful app creation, you would see something like below where you can navigate to settings>basic and copy client-id and client-secret

Note: The above steps may change on the Facebook developer page, depending on how long they keep the same UI.

Application Properties

  • Technically scope is a grant_type that is specific to the provider. In our case, Facebook has these two default scope which will grant to the client(our app) to access public profile and email once the user is authenticated. There are various scopes (see here) that you can define but that depends if your Facebook app is allowed to access or not.
  • Added Jsp view resolver mapping to look Jsp pages inside WEB-INF/jsp folder.

Login Page

Before jumping to spring security configuration what our expectation is, we want to have one custom login page where we can add the Sign In with Facebook button along with form where we can enter username password. Something like below —

Login page

Security Configuration

Keeping the login page in mind lets configure our security configuration.

Explanation: Okay so this is the main part that you need to understand that what we have done step by step.

While reading the below points parallelly map it with the configuration we did in the above code snippet.

Below is how you can read-

Hey spring-security (HttpSecurity technically)-

  • authorize all the request and let everyone access /login page (permitAll()) see line:8
  • After that, any request should be authenticated see line:9
  • And enable form-based login see line:10
  • And add a custom login page /login for form-based and redirect to /formLoginSuccess after successful authentication seeline:11
  • And enable logout (default URL would be /logout ) see line:12
  • And enable OAuth2Login flow see line:13
  • And add a custom login page /login (same as form-based) and redirect to /oauth2LoginSuccess once the user is authenticated from Facebook see line:14
  • And disable CSRF token. By default, it is enabled and this will force you to call /logout using HTTP POST instead of GET Method. So let's disable it for now. see line 15

After that configure form-based credentials-

Configure an in-memory username password so that we can use the login-form to submit a username password for authentication.see line:19 configure(AuthenticationManagerBuilder auth) methodfor more details in the above code snippet. Which is self-explanatory.

Things to know —

  • spring-security by default provides oauth2 client implementation for common providers like Facebook, Google, GitHub, and Okta. That is why we didn’t do anything just added facebook details in application.properties and bang!
  • When you enable OAuth2Login flow see line 13, by default spring-security enables authorization endpoint as /oauth2/authorization/{registerationId}. In our case, registration id is facebook(see application props)hence URL to trigger Facebook authorization would be /oauth2/authorization/facebook and our app will talk to Facebook for OAuth2 flow.
  • Since our application has two different login flow Oauth and form-based hence spring security stores user details into 2 different objects Oauth2User for OAuth-flow and UserDetails for form-based flow. We will see this in detail soon.

Adding Controller

Now we need to configure all the custom URLs that we have mentioned in the security configuration which is

1. /login page

Since we need to show custom login page so this is going to be like —

2. /oauth2LoginSuccessRequest Mapping

Once a user clicks on sign in with facebook , Oauth flow triggers our application will redirect the user to go on Facebook and enter the username password after successful authentication spring-security will redirect him to /oauth2LoginSuccess as we mention it in security config as default success URL.

A lot of things happens behind the scene in OAuth2 flow. Intent of this post is to cover basic confiugration and integration. We will understand flow in upcoming posts as we will dive in. Stay tunned !

Below is the request handler mapping code snippet —

Things to know —

When a user logs in in your application through OAuth2 Flow

  • The very first time your application won’t have any user details present in DB. So in /oauth2LoginSuccess method you can look into DB and see if the user is not present the DB then insert into DB and send a welcome email else to load other profile related information. [We will see this in an upcoming post when we will integrate this flow with DB]
  • Sometime you may need more user details from Facebook like first_name last_name which by default is not present inside OAuth2User object then here you have to make another call here to Facebook to get more details. So to do that you have to obtain facebook authenticated token first see line 17–20 in the above code snippet and pass that into rest call to facebook as Bearer <token>in header to fetch more details. We will see this next post when we will store the first name last name in DB.
  • To obtain user info you need to get OAuth2User object from OAuth2AuthenticationToken.getPricipal() and OAuth2User.getAttributes() will return you a map of user info.
  • @AuthenticationPricipal is a new annotation in spring security which extracts the authentication object. This is exactly similar to —

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

In OAuth2 login flow OAuth2User object is encapsulated inside authentication object which we can obtain via Authentication object or OAuth2AuthenticationToken.

3. /formLoginSuccessRequest Mapping

Once the user will enter a valid username password which is admin/admin in our case as we have defined in memory. After successful authentication user will be redirected to /formLoginSuccess

In form login flow UserDetails object encapsulated in authentication which we can obtain using authentication.getPrincipal()

Login Page HTML

I will leave it on you to understand below HTML :).

Home Page HTML

Home page after Facebook login

Home page username password flow

In both cases, we land on the same screen after successful authentication.

Summary

So far we have seen one of the simplest ways to integrate with Facebook along with form-based. Which most of us need in our application to support. But this is not enough. We need to customize it more and more and integrate it with DB. Add Forget-Password flow, Remember me, Or you may be looking for REST-based flow where you send Bearer <Token> in the response to the client (like angular) as many of us might be working in the microservices world. We will cover all the topics one by one in my upcoming posts. They are all in draft mode :).

👉🏽Check out the complete working code on my GitHub account.

PS: Your comments/claps keep me motivated to write more stuff like this. Please keep me motivated 😜.

--

--

Rajeev Shukla

Full-stack developer, Spring enthusiast , Java geek with a strong focus on code efficiency and simplicity.