[JAVA] SNS login with Spring Boot

Overview

This is a memo when the SNS login function is implemented in the web application created by Spring Boot.

environment

Java 8 (sorry) Spring Boot 2.1.0.RELEASE

Spring Social is EOL

https://projects.spring.io/spring-social/ https://spring.io/blog/2018/07/03/spring-social-end-of-life-announcement

Library used

https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-oauth2-client

Implementation target SNS

Implementation

①POM

pom.xml


<!-- OAuth2 authentication-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

②configuration

SecurityConfig



//Only the part related to login is excerpted.
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @NonNull
    SaveAndGenerateUserDetails saveAndGenerateUserDetails

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //SNS login
                .oauth2Login()
                    .loginPage("/login")
                    .userInfoEndpoint()
                    //Service class to be executed during OAuth authentication
                    .userService(new OAuth2UserService(saveAndGenerateUserDetails))
                    //Service class to be executed during OpenId authentication
                    .oidcUserService(new OidcUserDetailsService(saveAndGenerateUserDetails))
                .and()
                    //Implement SuccessHandler if needed
                    .successHandler(new MyAuthenticationSuccessHandler())
                    //Implement SuccessHandler if necessary. This time is the default.
                    .failureHandler(new SimpleUrlAuthenticationFailureHandler("/login?error"))
            .and()
                //ID PASS login can coexist
                .formLogin()
                    .loginPage("/login")
                        .usernameParameter("username")
                        .passwordParameter("password")
                        .permitAll()
                    .successHandler(new FormLoginSuccessHandler())
                    .failureHandler(new SimpleUrlAuthenticationFailureHandler("/login?error"))
            .and()
                .logout()
                    .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .logoutSuccessUrl("/")
                    .invalidateHttpSession(true)
                    .deleteCookies("JSESSIONID")
                    .permitAll()
            .and()
                .exceptionHandling();


}

③application.yml

application.yml


spring:
  security:
    oauth2:
      client:
        registration:
          facebook:
            client-id: 【client-id】
            client-secret: 【client-secret】
            scope:
              - email
              - public_profile
            redirect-uri:[Application URL]/login/oauth2/code/{registrationId}
          google:
            client-id: 【client-id】
            client-secret: 【client-secret】
            scope:
              - email
              - profile
              - openid
            redirect-uri:[Application URL]/login/oauth2/code/{registrationId}
        provider:
          facebook:
            authorizationUri: https://www.facebook.com/v3.3/dialog/oauth
            tokenUri: https://graph.facebook.com/v3.3/oauth/access_token
            userInfoUri: https://graph.facebook.com/v3.3/me

④view

login.html


<!--Create a link that sets the endpoint of each SNS login.
The endpoints are fixed values and are as follows.-->
<!--~ Various omissions ~-->
<a href="/oauth2/authorization/facebook">Facebook login</a>
<a href="/oauth2/authorization/google">Google login</a>
<!--~ Various omissions ~-->

⑤Service ⑤-1 OAuth class (set in .userService () of SecurityConfig)

OAuth2UserService.java


@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class OAuth2UserService
        extends DefaultOAuth2UserService {

    @NonNull
    SaveAndGenerateUserDetails saveAndGenerateUserDetails

    @Override
    @Transactional(readOnly = false)
    public OAuth2User loadUser(OAuth2UserRequest userRequest)
            throws OAuth2AuthenticationException {
        
        //I will omit the introduction of the implementation class.
        //Outline:
        //Create a class for each SNS to branch with registrationId and retrieve the information you want to get.
        //Save User information in DB based on the acquired information
        //Authentication information based on the acquired information(UserDetails)Will be returned.
        //The return type of this class differs depending on the authentication method, but the return type of the process method is MyUserDetails.
        //So here we will absorb the difference in authentication method.
        return saveAndGenerateUserDetails.process(userRequest,
                super.loadUser(userRequest));
    }
}

⑤-2 Processing after OpenId authentication (set in .oidcUserService () of SecurityConfig)

OidcUserDetailsService.java


@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class OidcUserDetailsService
        extends OidcUserService {

    @NonNull
    SaveAndGenerateUserDetails saveAndGenerateUserDetails;

    @Override
    @Transactional(readOnly = false)
    public OidcUser loadUser(OidcUserRequest userRequest)
            throws OAuth2AuthenticationException {
        
        // ⑤-Same as 1
        return saveAndGenerateUserDetails.process(userRequest,
                super.loadUser(userRequest));
    }
}

⑥ MyUserDetails class

MyUserDetails.java


@SuppressWarnings("serial")
@Data
public class MyUserDetails implements UserDetails, OAuth2User, OidcUser {

    // @What method should be overridden?
    //Only the parts necessary for SNS login are excerpted.

    private Map<String, Object> attributes;

    //constructor
    public MyUserDetails(MyUser user, Map<String, Object> attr) {
        //Only OAuth and OpenId information is listed.
        this.attributes = attr;
    }
}

Impressions

・ There were fewer classes to prepare by myself than I expected. ・ It would be nice if the library did something good, but it was a black box. ・ If you implement one type of oauth and one type of openid, you can easily expand horizontally.

Reference URL

Recommended Posts

SNS login with Spring Boot
Download with Spring Boot
Try to implement login function with Spring Boot
Generate barcode with Spring Boot
Hello World with Spring Boot
Implement GraphQL with Spring Boot
Get started with Spring boot
Hello World with Spring Boot!
File upload with Spring Boot
Spring Boot starting with copy
Login function with Spring Security
Spring Boot starting with Docker
Hello World with Spring Boot
Set cookies with Spring Boot
Use Spring JDBC with Spring Boot
Add module with Spring Boot
Getting Started with Spring Boot
Create microservices with Spring Boot
Send email with spring boot
Spring Boot + Java + GitHub authentication login
Use Basic Authentication with Spring Boot
gRPC on Spring Boot with grpc-spring-boot-starter
Create an app with Spring Boot 2
Hot deploy with Spring Boot development
Database linkage with doma2 (Spring boot)
Spring Boot programming with VS Code
Until "Hello World" with Spring Boot
Inquiry application creation with Spring Boot
Get validation results with Spring Boot
(Intellij) Hello World with Spring Boot
Create an app with Spring Boot
Google Cloud Platform with Spring Boot 2.0.0
Check date correlation with Spring Boot
I tried GraphQL with Spring Boot
[Java] LINE integration with Spring Boot
Beginning with Spring Boot 0. Use Spring CLI
I tried Flyway with Spring Boot
Message cooperation started with Spring Boot
Spring Boot gradle build with Docker
I implemented an OAuth client with Spring Boot / Security (LINE login)
Hello World with Eclipse + Spring Boot + Maven
Send regular notifications with LineNotify + Spring Boot
Part 1: Try using OAuth 2.0 Login supported by Spring Security 5 with Spring Boot
HTTPS with Spring Boot and Let's Encrypt
Challenge Spring Boot
Try using Spring Boot with VS Code
Start web application development with Spring Boot
Launch Nginx + Spring Boot application with docker-compose
I tried Lazy Initialization with Spring Boot 2.2.0
Spring Boot Form
Implement CRUD with Spring Boot + Thymeleaf + MySQL
Asynchronous processing with Spring Boot using @Async
Implement paging function with Spring Boot + Thymeleaf
Spring Boot Memorandum
gae + spring boot
(IntelliJ + gradle) Hello World with Spring Boot
Use cache with EhCashe 2.x with Spring Boot
Form class validation test with Spring Boot
Run WEB application with Spring Boot + Thymeleaf
Achieve BASIC authentication with Spring Boot + Spring Security
Spring Boot environment construction with Docker (January 2021 version)