In this article, I’d like to share with you guys, about how to implement social login functionality with both Google and Facebook in a web application based on Java Spring Boot. In other words, it lets end users sign in your application using their own Google or Facebook account, besides traditional username and password login.

To follow this guide, first you should understand how to integrate social login only with Google or Facebook, by following these tutorials:

In this tutorial, I will also share some code examples that determine whether a user is authenticated via Google or Facebook, and run custom code upon successful authentication. The code below are used in real life projects such as E-commerce shopping website, which you can learn in the Spring Boot E-Commerce Ultimate Course.

 

1. Configure OAuth2 Google and Facebook Clients in application.yml

In the Spring Boot application configuration file (application.yml), declare the Spring Security OAuth2 client registration for Google and Facebook as follows:

spring:
  security:
    oauth2:
      client:
        registration:
         google:
          clientId: YOUR_GOOGLE_APP_CLIENT_ID
          clientSecret: YOUR_GOOGLE_APP_SECRET_KEY
          scope:
           - email
           - profile
                   
         facebook:
          clientId: YOUR_FACEBOOK_APP_CLIENT_ID
          clientSecret: YOUR_FACEBOOK_APP_SECRET_KEY
          scope:
           - email
           - public_profile
Replace the actual values of Client ID and Secret Key of your Google and Facebook OAuth apps.


2. Update Login Page

Next, update the login page to show 2 hyperlinks: Login with Facebook and Login with Google, with the URLs as follows:

...
<a th:href="/@{/oauth2/authorization/facebook}">Login with Facebook</a>
...
<a th:href="/@{/oauth2/authorization/google}">Login with Google</a>
...
The login page would look something like this:

Login Page with Google and Facebook



As you can see, the user can choose to sign in via Facebook, Google or username (email) and password.

That’s it! Now you can test login with Google and Facebook. Pretty simple, right?

Read on if you want to do more, e.g. determine whether a user is logged in via Facebook or Google; and run custom logics upon successful authentication.


3. Update OAuth2User and OAuth2UserService

Update the loadUser() method in your customer OAuth2UserService class as follows:

package net.codejava.security.oauth;

@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService  {

	@Override
	public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
		String clientName = userRequest.getClientRegistration().getClientName();
		OAuth2User user =  super.loadUser(userRequest);
		return new CustomOAuth2User(user, clientName);
	}

}
Here, the statement that helps identifying whether the user signed in via Google or Facebook is this:

String clientName = userRequest.getClientRegistration().getClientName();
The variable clientName could be either Google or Facebook.

And also update your custom OAuth2User class as follows:

package net.codejava.security.oauth;

public class CustomOAuth2User implements OAuth2User {
	private String oauth2ClientName;
	private OAuth2User oauth2User;
	
	public CustomOAuth2User(OAuth2User oauth2User, String oauth2ClientName) {
		this.oauth2User = oauth2User;
		this.oauth2ClientName = oauth2ClientName;
	}

	@Override
	public Map<String, Object> getAttributes() {
		return oauth2User.getAttributes();
	}

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return oauth2User.getAuthorities();
	}

	@Override
	public String getName() {
		System.out.println(oauth2User.<String>getAttribute("email"));
		return oauth2User.getAttribute("name");
	}

	public String getEmail() {
		return oauth2User.<String>getAttribute("email");		
	}

	public String getOauth2ClientName() {
		return this.oauth2ClientName;
	}
}
Here, we code the getOauth2ClientName() method that returns the name of OAuth2 client application, which could be Facebook or Google.


4. Code Authentication Success Handlers

Suppose that we want to update authentication type of the user who has signed in. So update the User entity class as follows:

package net.codejava.user;

@Entity
@Table(name = "users")
public class User {
	
	@Enumerated(EnumType.STRING)
	@Column(name = "auth_type")
	private AuthenticationType authType;

	public AuthenticationType getAuthType() {
		return authType;
	}

	public void setAuthType(AuthenticationType authType) {
		this.authType = authType;
	}

	// other fields, getters and setters are not shown	
}
As you can see, we add a new field of a custom enum type AuthenticationType, that maps to the column auth_type in the users table. And the enum type would be declared like this:

package net.codejava.user;

public enum AuthenticationType {
	DATABASE, FACEBOOK, GOOGLE
}
Then code an authentication success handler as follows:

package net.codejava.security.oauth;

@Component
public class OAuthLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	@Autowired UserService userService;
	
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws ServletException, IOException {
		CustomOAuth2User oauth2User = (CustomOAuth2User) authentication.getPrincipal();
		String oauth2ClientName = oauth2User.getOauth2ClientName();
		String username = oauth2User.getEmail();
		
		userService.updateAuthenticationType(username, oauth2ClientName);
		
		super.onAuthenticationSuccess(request, response, authentication);
	}

}
Here, upon successful authentication it calls the UserService to update user’s authentication type. Code of the UserService class:

package net.codejava.user;

@Service
@Transactional
public class UserService {
    @Autowired
    private UserRepository repo;
    
    public void updateAuthenticationType(String username, String oauth2ClientName) {
    	AuthenticationType authType = AuthenticationType.valueOf(oauth2ClientName.toUpperCase());
    	repo.updateAuthenticationType(username, authType);
    }	
}
And code of the UserRepository interface:

package net.codejava.user;

public interface UserRepository extends CrudRepository<User, Long> {
	
	@Modifying
	@Query("UPDATE User u SET u.authType = ?2 WHERE u.username = ?1")
	public void updateAuthenticationType(String username, AuthenticationType authType);
}
For login using username (email) and password in database, code another authentication success handler as follows:

package net.codejava.security;

@Component
public class DatabaseLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	@Autowired UserService userService;
	
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws ServletException, IOException {
		MyUserDetails userDetails = (MyUserDetails) authentication.getPrincipal();
		userService.updateAuthenticationType(userDetails.getUsername(), "database");
		super.onAuthenticationSuccess(request, response, authentication);
	}

}
And finally, update the Spring Security configuration class as follows, in order to use the authentication success handlers written above:

package net.codejava.security;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.antMatchers("/", "/login").permitAll()
			.anyRequest().authenticated()
			.and()
			.formLogin().permitAll()
				.loginPage("/login")
				.usernameParameter("email")
				.passwordParameter("pass")
				.successHandler(databaseLoginSuccessHandler)				
			.and()
			.oauth2Login()
				.loginPage("/login")
				.userInfoEndpoint()
					.userService(oauth2UserService)
				.and()
				.successHandler(oauthLoginSuccessHandler)
			.and()
			.logout().logoutSuccessUrl("/").permitAll()
			.and()
			.exceptionHandling().accessDeniedPage("/403")
			;
	}
	
	@Autowired
	private CustomOAuth2UserService oauth2UserService;
	
	@Autowired
	private OAuthLoginSuccessHandler oauthLoginSuccessHandler;
	
	@Autowired
	private DatabaseLoginSuccessHandler databaseLoginSuccessHandler;
}
So that’s you have learned how to integrate social login function with Google and Facebook in a Spring Boot application via practical code examples. I hope you found this article helpful. To see the coding in action, I recommend you watch the following video:

You can also download the reference project under the Attachment section below, or clone the sample project from this GitHub repo.

 

Related Spring OAuth2 Tutorials:

 

Related Spring Security Tutorials:

 

Other Spring Boot Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.



Attachments:
Download this file (SpringBootGogleFacebookLogin.zip)SpringBootGogleFacebookLogin.zip[Sample Spring Boot project]104 kB

Add comment

   


Comments 

#7saurav2024-02-24 13:43
hi , i would like to implement in spring mvc can you please telll me the steps and configurations ?

i will be very helpful for me
Quote
#6hao2023-09-14 07:01
thank you so much for your supporting
Quote
#5David2023-04-01 19:05
Would be good if you included code for front end and other stuff your using in this tutorial as well
Quote
#4Rotha2022-06-08 21:20
Thank you so much for this helpful tutorial.
Quote
#3kamil anees2022-02-06 22:22
Hi sir, can we implement JWT in this project, if possible kindly guide me
Quote