Part-2: Authorising user using Spring Social (Google, Facebook, LinkedIn) and Spring Security - Little Big Extra Skip to main content

Part-2: Authorising user using Spring Social (Google, Facebook, LinkedIn) and Spring Security

Part-2: Authorising user using Spring Social (Google, FaceBook and LinkedIn) and Spring Security

 

Introduction

In the last part, I had demonstrated how we can use spring-social to authorize user using Facebook, Google and LinkedIn API’s. If you have not read the last part, I would request you to have a look and then come back to this part.

In this part, I am going to use spring security to allow only logged in users or authenticated users to navigate to secure pages, any user attempting to go to secure pages will be redirected to the Login page for authentication.
Once the user is authenticated, we will save his details to in-memory DB and then the user can log out and log in again.

Spring Security framework provides both authentication and authorization feature for applications. It also helps in preventing attacks like session fixation, clickjacking, cross-site request forgery, etc and good thing is that it can be customized easily to fit in different use cases.
In this tutorial, we will add spring security with spring social API to register users and then add the log on and log out functionality.

Step 1 – Adding Maven dependencies

The first step to start will be adding maven dependencies for Spring-security and also for thymeleaf-extras-spring security for using spring-security tags for displaying logged in user and roles etc on pages.
Add the following dependencies to the POM.xml

Step 2 – Registering user on site

When logging on to social networking platforms, we didn’t need any form as we fetch the user details through the API. However, to register a user we will need a simple form to capture their details. We will create a view called registration.html under src/main/resources/templates/registration.html.
This form will have server-side validation and minimal CSS/JS


Source code of Registration page is as below

Modifying the Controller

To serve this Page, we will modify the existing Login controller

Modifying the Login Page

Now let’s modify the login page and add the registration link on the home page, also we will add username and password fields so once the user is registered they can also log in.

This HTML fragment will add a username/password field along with an error message, in case of the user not found.


 

Also, let’s add another code fragment which is to display the Logged In user, the role assigned and a Logout button


 

We will also need to csrf token to our existing forms for Google, Facebook and LinkedIn

This is how the Complete login.html looks like.

Login Page

Source code of login.html

Step 3 – Saving User to Database

Once the user is authenticated, we will need to save their details in a database. So we will use the annotations like @Entity and @Table to create an in-memory database(HSQLDB) and tables if they don’t exist. The DB details can be easily configured in application.properties,also the DB type can also be changed easily.
We will use the hibernate validator annotations @NotNull,@Size to make sure that input fields are validated on the server side before they can be, you can add client-side javascript if that suits.

Saving the Bean using JPA Repository

We will be using to retrieve user details and save them.
Now we will create a new interface called UserRepository in package com.login.repository this interface will extend the JPARespository<T, ID> where T is UserBean in our Case and ID is the email(primary key).
We will define the abstract method findByEmail by passing email which has been defined as a primary key in UserBean class. To get the UserBean for a particular method all we need to do is inject the UserRepository and call findByemail method()

The key advantage of using Spring Data is that it makes virtually our code DAO implementation-free, only above interface will be able to save and retrieve user details.

Step 4 – Adding the Spring Security

This is the crux of this tutorial, we will use the spring security to define which URL’s can be accessed only by insecurely and which one can only be accessed by login user.

We will add a class called SecurityConfig to allow users to

  • Allow URLs which start with CSS/** and /connect** to be accessed by all users
  • Allow /secure/* URL to be accessed only by logged in User
  • If any secure/* is accessed by unauthenticated user, redirect him to login page
  • In case of unsuccessful authentication, redirect user to /login-error
  • Add logout functionality

As you might have noticed that we have added a bean for BCryptPasswordEncoder, this bean will be used for encrypting the password as hash, which is one of the safest technique to store passwords and decrypting hash is very tough ( Maybe not as tough as mining a BitCoin 🙂 )

Also, there is another method configureglobal(AuthenticationManagerBuilder auth) which basically defines that we have defined our own custom implementation of UserDetailsService, we will talk about it later.

Move user.html to secure/user.html

Since now we want our user.html to be only presented for logged in users we will move user.html from src/main/resources/templates to src/main/resources/templates/secure/user.html
Also, we will add the thymleaf authentication tags to display logged in Username and role.
This is how the complete user.html looks like, make sure it is in src/main/resources/templates/secure/user.html

Step 6 – Adding UserDetails service, our own implementation

This is the crucial step as would define here what to do when the user puts in his username/password combination.
If we want user authentication by a DAO class, we need to implement the UserDetailsService interface. This interface has loadUserByUsername() method which is used to validate the user, of course, we need to provide the implementation.

Remeber this method in Security config

Providing our own implementation of UserDetailsService

We will write the implementation of method loadUserByUsername.In this method, we will do couple of things

  • Find Username in DB, if not found throw an exception
  • If the user is found, login user and return the User object of type org.springframework.security.core.userdetails.User, spring will automatically update the Security context for us.

Step 7 – Setting Security context (auto login)

Once the user is logged in by social providers or by registering a user we need to update security context by setting the authentication

As per the spring API – “Authentication represents the token for an authentication request or for an authenticated principal once the request has been processed by the AuthenticationManager.authenticate(Authentication) method.
Once the request has been authenticated, the Authentication will usually be stored in a thread-local SecurityContext managed by the SecurityContextHolder by the authentication mechanism which is being used. An explicit authentication can be achieved, without using one of Spring Security’s authentication mechanisms, by creating an Authentication instance and using the code:

SecurityContextHolder.getContext().setAuthentication(authentication)

Which is exactly we are going to do in our method.

Step 8 – Changing the Login controller

Since now we have most of the things in place, we need to add the controller so when the registration form is submitted,

  • We need to save the user details on DB
  • Update the security context and set the authentication object
  • Redirect user to secure page.

Also, since in our Security config, we defined a “/login-error” path, we will handle that too in the same controller.

Step 9 – Modifying the Social Providers

In previous post we had created the FacebookProvider, GoogleProvider and LinkedInProvider now we need to make some changes in them so they

  • Save the user details on DB
  • Update the security context and set the authentication object
  • Redirect the user to secure page.

In our class BaseProvider.java, we will add saveUserDetails and autoLoginUser method

In our provider classes(FacebookProvider, GoogleProvider and LinkedInProvider) we just need to add the code to

    Save the details in DB
    baseProvider.saveUserDetails(userForm);
    Login the User
    baseProvider.autoLoginUser(userForm);
    and also return back the secure page
    return "secure/user"

 

You will need to do these changes in all 3 classes(GoogleProvider, FaceBookProvider and LinkedInProvider)

Step 10 – Controller for /secure URL

Remeber, we have added in our  defaultSuccessUrl("/secure/user") SecurityConfig, well this is the page where we want the user to redirect, once they are authenticated.

Also on user/secure.html, we have defined th:object="${loggedInUser}" this attribute also needs to be initialized once the user is logged in by security config. So the question is how do we initialize the "${loggedInUser}" model attribute. If we don’t initialise it we will get an error.
An easy way to fix this problem is to use annotation called @ModelAttribute @ModelAttribute("loggedInUser"). If this annotation has been used all the RequestMapping method in the controller will be called only after the annotated method.

We can define a method where we will get the Authentication object and then use that object to find the user details.

Also, we need to define the method for mapping @GetMapping("/secure/user") as shown below. Since we need to initialize model attribute ${loggedInUser} only for @GetMapping("/secure/user") we need to define it in a separate controller class.

Step 11 – Updating the properties file

Since we are using HSQLDB in this example and spring boot will configure most of the things for us, we don’t need to do more than defining a couple of properties for initializing the database. Add these properties in application.properties

Conclusion

Spring Social and Spring Security are very flexible and easily customizable for different use cases. They both can be used together to provide a seamless and smooth log in experience for users. The above code is just a step in explaining how both the offerings (Spring Social and Spring Security) can be used in unison.

For readers benefit, above code can be cloned from

This is how the project structure looks like

 

This is how the screen looks like after user is logged in, the logged in user and the roles are being displayed on top of screen. 

Related Posts

5 thoughts to “Part-2: Authorising user using Spring Social (Google, Facebook, LinkedIn) and Spring Security”

  1. When i running the demo, I choose login with google+, i callback url is localhost:3000, but the forward url
    redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fconnect%2Fgoogle, it’s auto add /connect/google, I don’t know why, so google has a error 400, The redirect URI in the request, , does not match the ones authorized for the OAuth client.

  2. I have written reply for wrong part.So I am writing again. Thanks for this useful tutorial. When I use with spring boot 2.2.1 version SocialAutoConfigurerAdapter class can not be resolved. How to use this adapter with 2.2.1 and also non auto config.

Leave a Reply

Your email address will not be published. Required fields are marked *

Bitnami