DEV Community

FullStackJava
FullStackJava

Posted on

Spring Security Using Facebook Authorization: A Comprehensive Guide

In today's digital landscape, integrating third-party login mechanisms into applications has become a standard practice. It enhances user experience by allowing users to log in with their existing social media accounts. In this blog post, we will walk through the process of integrating Facebook authorization into a Spring Boot application using Spring Security.

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setting Up Facebook Developer Account
  4. Creating a Spring Boot Application
  5. Configuring Spring Security for OAuth2 Login
  6. Handling Facebook User Data
  7. Testing the Integration
  8. Conclusion

1. Introduction

OAuth2 is an open standard for access delegation, commonly used for token-based authentication. Facebook, among other social media platforms, supports OAuth2, making it possible to integrate Facebook login into your Spring Boot application.

2. Prerequisites

Before we start, ensure you have the following:

  • JDK 11 or later
  • Maven
  • An IDE (e.g., IntelliJ IDEA or Eclipse)
  • A Facebook Developer account

3. Setting Up Facebook Developer Account

To use Facebook login, you need to create an app on the Facebook Developer portal:

  1. Go to the Facebook Developer website and log in.
  2. Click on "My Apps" and then "Create App."
  3. Choose an app type (e.g., "For Everything Else") and provide the required details.
  4. Once the app is created, go to "Settings" > "Basic" and note down the App ID and App Secret.
  5. Add a product, select "Facebook Login," and configure the Valid OAuth Redirect URIs to http://localhost:8080/login/oauth2/code/facebook.

4. Creating a Spring Boot Application

Create a new Spring Boot project with the necessary dependencies. You can use Spring Initializr or add the dependencies manually to your pom.xml.

Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
</dependencies>
Enter fullscreen mode Exit fullscreen mode

5. Configuring Spring Security for OAuth2 Login

Next, configure Spring Security to use Facebook for OAuth2 login.

application.properties

Add your Facebook app credentials to src/main/resources/application.properties.

spring.security.oauth2.client.registration.facebook.client-id=YOUR_FACEBOOK_APP_ID
spring.security.oauth2.client.registration.facebook.client-secret=YOUR_FACEBOOK_APP_SECRET
spring.security.oauth2.client.registration.facebook.redirect-uri-template={baseUrl}/login/oauth2/code/{registrationId}
spring.security.oauth2.client.registration.facebook.scope=email,public_profile
spring.security.oauth2.client.registration.facebook.client-name=Facebook
spring.security.oauth2.client.registration.facebook.authorization-grant-type=authorization_code
spring.security.oauth2.client.provider.facebook.authorization-uri=https://www.facebook.com/v11.0/dialog/oauth
spring.security.oauth2.client.provider.facebook.token-uri=https://graph.facebook.com/v11.0/oauth/access_token
spring.security.oauth2.client.provider.facebook.user-info-uri=https://graph.facebook.com/me?fields=id,name,email
spring.security.oauth2.client.provider.facebook.user-name-attribute=id
Enter fullscreen mode Exit fullscreen mode

Security Configuration

Create a security configuration class to handle the OAuth2 login.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests(authorizeRequests ->
                authorizeRequests
                    .antMatchers("/", "/error", "/webjars/**").permitAll()
                    .anyRequest().authenticated()
            )
            .oauth2Login(oauth2Login ->
                oauth2Login
                    .loginPage("/login")
                    .userInfoEndpoint(userInfoEndpoint ->
                        userInfoEndpoint
                            .oidcUserService(this.oidcUserService())
                            .userService(this.oAuth2UserService())
                    )
                    .failureHandler(new SimpleUrlAuthenticationFailureHandler())
            );
    }

    private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
        final OidcUserService delegate = new OidcUserService();
        return (userRequest) -> {
            OidcUser oidcUser = delegate.loadUser(userRequest);

            // Custom logic here

            return oidcUser;
        };
    }

    private OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService() {
        final DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();
        return (userRequest) -> {
            OAuth2User oAuth2User = delegate.loadUser(userRequest);

            // Custom logic here

            return oAuth2User;
        };
    }
}
Enter fullscreen mode Exit fullscreen mode

6. Handling Facebook User Data

After a successful login, you might want to handle and display user data.

Custom User Service

Create a custom service to process user details.

import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Set;
import java.util.HashMap;

@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {

    private final DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) {
        OAuth2User oAuth2User = delegate.loadUser(userRequest);

        Map<String, Object> attributes = new HashMap<>(oAuth2User.getAttributes());
        // Additional processing of attributes if needed

        return oAuth2User;
    }
}
Enter fullscreen mode Exit fullscreen mode

Controller

Create a controller to handle login and display user info.

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class LoginController {

    @GetMapping("/login")
    public String getLoginPage() {
        return "login";
    }

    @GetMapping("/")
    public String getIndexPage(Model model, @AuthenticationPrincipal OAuth2User principal) {
        if (principal != null) {
            model.addAttribute("name", principal.getAttribute("name"));
        }
        return "index";
    }
}
Enter fullscreen mode Exit fullscreen mode

Thymeleaf Templates

Create Thymeleaf templates for login and index pages.

src/main/resources/templates/login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
</head>
<body>
    <h1>Login</h1>
    <a href="/oauth2/authorization/facebook">Login with Facebook</a>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

src/main/resources/templates/index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Home</title>
</head>
<body>
    <h1>Home</h1>
    <div th:if="${name}">
        <p>Welcome, <span th:text="${name}">User</span>!</p>
    </div>
    <div th:if="${!name}">
        <p>Please <a href="/login">log in</a>.</p>
    </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

7. Testing the Integration

Run your Spring Boot application and navigate to http://localhost:8080. Click on the "Login with Facebook" link and authenticate with your Facebook credentials. If everything is set up correctly, you should be redirected to the home page with your Facebook profile name displayed.

Integrating Facebook login into your Spring Boot application using Spring Security enhances user experience and leverages the power of OAuth2. With this setup, users can easily log in with their existing Facebook accounts, providing a seamless and secure authentication process.

By following this guide,

Top comments (0)