Add social based login (Google, Facebook, and Github) to your Spring Boot application using OAuth2 functionalities

In the tutorial, we will explain how to add social-based login to a Spring boot application using a Spring Security function called OAuth2. We use MySQL database and React for the frontend.

App Screenshot

Creating the Project

You can create a project using the Spring Initializr web tool http://start.spring.io, follows the introduction to fill in the information:

  • Artifact: ozenero-spring-social
  • Dependencies: Spring Web, Spring Security, OAuth2 Client, Spring Data JPA, MySQL Driver, Validation

After that, you can click Generate and download your project

Creating OAuth2 apps for social login

You need to create an app in OAuth2 provider console to enable social login with an OAuth2 provider. After that, you can get AppID and AppSecret (also called ClientId and Client Secret). OAuth2 providers use the AppID and AppSecret to identify your app. Some other settings include:

  • Authorized redirect URIs: A valid list of redirect URIs to redirect users after granting or rejecting permission to the app.
  • Scope: used to ask users for permission to access data.

Creating Facebook, Github, and Google Apps

Configuring the Spring Boot application

By default, Spring boot reads configurations from the file src/main/resource/application.properties. It also supports .yaml format. Rename application.properties file to application.yaml and add the following configurations.

spring:
    datasource:
        url: jdbc:mysql://localhost:3306/spring_social?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
        username: root
        password: callicoder

    jpa:
        show-sql: true
        hibernate:
            ddl-auto: update
            naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
        properties:
            hibernate:
                dialect: org.hibernate.dialect.MySQL5InnoDBDialect
    security:
      oauth2:
        client:
          registration:
            google:
              clientId: your_id.apps.googleusercontent.com
              clientSecret: your_secret
              redirectUri: "{baseUrl}/oauth2/callback/{registrationId}"
              scope:
                - email
                - profile
            facebook:
              clientId: your_id
              clientSecret: your_secret
              redirectUri: "{baseUrl}/oauth2/callback/{registrationId}" # Note that facebook now mandates the use of https redirect URIs, so make sure your app supports https in production
              scope:
                - email
                - public_profile
            github:
              clientId: your_id
              clientSecret: your_secret
              redirectUri: "{baseUrl}/oauth2/callback/{registrationId}"
              scope:
                - user:email
                - read:user
          provider:
            facebook:
              authorizationUri: https://www.facebook.com/v3.0/dialog/oauth
              tokenUri: https://graph.facebook.com/v3.0/oauth/access_token
              userInfoUri: https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture.width(250).height(250)
app:
  auth:
    tokenSecret: your_token_secret
    tokenExpirationMsec: 864000000
  cors:
    allowedOrigins: http://localhost:3000 # Comma separated list of allowed origins
  oauth2:
    # After successfully authenticating with the OAuth2 Provider,
    # we'll be generating an auth token for the user and sending the token to the
    # redirectUri mentioned by the client in the /oauth2/authorize request.
    # We're not using cookies because they won't work well in mobile clients.
    authorizedRedirectUris:
      - http://localhost:3000/oauth2/redirect
      - myandroidapp://oauth2/redirect
      - myiosapp://oauth2/redirect

The data source includes MySQL database configurations. Database name is spring_social, please modify spring.datasource.username and spring.datasource.password.

In security:oauth2:client:registration:, the configurations include all details of oauth2 providers. Inapp.auth, its config the JWT authentication token when the user logged in successfully.

In redirectUriTemplate property in all the registered oauth2 providers, when you create an app in the OAuth2 providers, you have to add an authorized redirect URI which matches the template. In this case, for a google app, we config the authorizedRedirectURI http://localhost:8080/oauth2/callback/google.

Binding AppProperties

In the next step, we bind all configurations prefixed with app to a POJO class using Spring Boot’s @ConfigurationProperties feature

package com.example.springsocial.config;

import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.ArrayList;
import java.util.List;

@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private final Auth auth = new Auth();
    private final OAuth2 oauth2 = new OAuth2();

    public static class Auth {
        private String tokenSecret;
        private long tokenExpirationMsec;

        public String getTokenSecret() {
            return tokenSecret;
        }

        public void setTokenSecret(String tokenSecret) {
            this.tokenSecret = tokenSecret;
        }

        public long getTokenExpirationMsec() {
            return tokenExpirationMsec;
        }

        public void setTokenExpirationMsec(long tokenExpirationMsec) {
            this.tokenExpirationMsec = tokenExpirationMsec;
        }
    }

    public static final class OAuth2 {
        private List<String> authorizedRedirectUris = new ArrayList<>();

        public List<String> getAuthorizedRedirectUris() {
            return authorizedRedirectUris;
        }

        public OAuth2 authorizedRedirectUris(List<String> authorizedRedirectUris) {
            this.authorizedRedirectUris = authorizedRedirectUris;
            return this;
        }
    }

    public Auth getAuth() {
        return auth;
    }

    public OAuth2 getOauth2() {
        return oauth2;
    }
}

Enabling AppProperties

In order to enable the properties, we add the@EnableConfigurationProperties annotation. Let’s open the main application class SpringSocialApplication.java and add the annotation like below.

package com.example.springsocial;

import com.example.springsocial.config.AppProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class)
public class SpringSocialApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringSocialApplication.class, args);
	}
}

Enabling CORS

In order to enable CORS to allow our frontend client can access the APIs from a different origin. We need to enable the origin http://localhost:3000 where the frontend application will be running.

package com.example.springsocial.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    private final long MAX_AGE_SECS = 3600;

    @Value("${app.cors.allowedOrigins}")
    private String[] allowedOrigins;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
        .allowedOrigins(allowedOrigins)
        .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
        .allowedHeaders("*")
        .allowCredentials(true)
        .maxAge(MAX_AGE_SECS);
    }
}

Creating the database entities

Let’s now create the Entity classes of our application. Following is the definition of the User class –

In the next step, we create Entity classes for the application. You can define the User class like below.

package com.example.springsocial.model;
import com.fasterxml.jackson.annotation.JsonIgnore;

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;

@Entity
@Table(name = "users", uniqueConstraints = {
        @UniqueConstraint(columnNames = "email")
})
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @Email
    @Column(nullable = false)
    private String email;

    private String imageUrl;

    @Column(nullable = false)
    private Boolean emailVerified = false;

    @JsonIgnore
    private String password;

    @NotNull
    @Enumerated(EnumType.STRING)
    private AuthProvider provider;

    private String providerId;

    // Getters and Setters (Omitted for brevity)
}

The User class contains information about the authentication provider. Following is the definition of the AuthProvider enum –

In the User class, it provides information related to the authentication provider. Here is the definition of the AuthProvider enum.

package com.example.springsocial.model;

public enum  AuthProvider {
    local,
    facebook,
    google,
    github
}

Creating the repositories for accessing data from the database

Let’s create the repository layer for accessing data from the database. The following UserRepository interface provides database functionalities for the User entity. Thanks to Spring-Data-JPA, we don’t need to write much code here

In order to create the repository layer for accessing data from the database, we need to config theUserRepository interface to provide database functionalities for the User entity. Refer to Spring-Data-JPA  for the code

package com.example.springsocial.repository;

import com.example.springsocial.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    Optional<User> findByEmail(String email);

    Boolean existsByEmail(String email);

}

In this article, we introduce how to configure an application and defined the entity classes and repositories.

Angular 13 Spring WebFlux MongoDB CRUD Operations

In this tutorial, we’re gonna build a full Reactive Application in which, Spring WebFlux, Spring Data Reactive MongoDB are used for backend, and Angular, RxJS, EventSource are on client side.

Related Posts:
How to use Angular Http Client to fetch Data from SpringBoot RestAPI – Angular 13
How to use Angular HttpClient to POST, PUT, DELETE data on SpringBoot Rest APIs – Angular 13
How to build SpringBoot MongoDb RestfulApi
How to use SpringData MongoRepository to interact with MongoDB
Angular 13 + Spring Boot + MongoDB CRUD example
Introduction to RxJS – Extensions for JavaScript Reactive Streams

Continue reading “Angular 13 Spring WebFlux MongoDB CRUD Operations”

How to Integrate Angular 13 & SpringBoot 2.0 RestAPI – SpringToolSuite

In the tutorial, we show you how to integrate Angular 13 with SpringBoot RestAPI for development using SpringToolSuite IDE.

Related posts:
Angular 13 Component – How to create & integrate New Angular 13 Component
Angular 13 Service – with Observable Data for Asynchronous Operation

Spring Boot + Angular 13 example | Spring Data JPA + REST + PostgreSQL CRUD example
Spring Boot + Angular 13 example | Spring Data JPA + REST + MySQL CRUD example
Angular 13 HttpClient + Spring Boot + MariaDB example | Spring Data JPA + RestAPIs CRUD example
Spring Boot + Angular 13 example | Spring Data + REST + MongoDb CRUD example
Spring Boot + Angular 13 example | Spring Data + REST + Cassandra CRUD example

Continue reading “How to Integrate Angular 13 & SpringBoot 2.0 RestAPI – SpringToolSuite”

Angular 13 SpringBoot CRUD Mariadb Example

In this tutorial, we show you Angular 13 Http Client & Spring Boot Server example that uses Spring JPA to do CRUD with MariaDB and Angular 13 as a front-end technology to make request and receive response.

Related Posts:
Spring Boot + Angular 13 example | Spring Data JPA + REST + MySQL CRUD example
Spring Boot + Angular 13 example | Spring Data JPA + REST + PostgreSQL CRUD example
Spring Boot + Angular 13 example | Spring Data + REST + Cassandra CRUD example
How to use Spring JPA with PostgreSQL | Spring Boot

Related Pages:

Continue reading “Angular 13 SpringBoot CRUD Mariadb Example”

Angular 8 Spring WebFlux MongoDB CRUD RestAPI

In this tutorial, we’re gonna build a full Reactive Application in which, Spring WebFlux, Spring Data Reactive MongoDB are used for backend, and Angular, RxJS, EventSource are on client side.

Related Posts:
How to use Angular Http Client to fetch Data from SpringBoot RestAPI – Angular 8
How to use Angular HttpClient to POST, PUT, DELETE data on SpringBoot Rest APIs – Angular 8
How to build SpringBoot MongoDb RestfulApi
How to use SpringData MongoRepository to interact with MongoDB
Angular 8 + Spring Boot + MongoDB CRUD example
Introduction to RxJS – Extensions for JavaScript Reactive Streams

Continue reading “Angular 8 Spring WebFlux MongoDB CRUD RestAPI”