This is a memo when the SNS login function is implemented in the web application created by Spring Boot.
Java 8 (sorry) Spring Boot 2.1.0.RELEASE
https://projects.spring.io/spring-social/ https://spring.io/blog/2018/07/03/spring-social-end-of-life-announcement
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-oauth2-client
①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;
}
}
・ 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.
Recommended Posts