Skip to content

Commit

Permalink
#97 - Add OAuth authentication configuration
Browse files Browse the repository at this point in the history
Add configuration to allow Spring Security to accept both existing DB authentication and OAuth authentication.
  • Loading branch information
laphayen committed Jul 28, 2024
1 parent 5da8375 commit 9f8cbe6
Showing 1 changed file with 70 additions and 25 deletions.
95 changes: 70 additions & 25 deletions src/main/java/com/laphayen/projectboard/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,53 +1,98 @@
package com.laphayen.projectboard.config;

import com.laphayen.projectboard.dto.UserAccountDto;
import com.laphayen.projectboard.dto.security.BoardPrincipal;
import com.laphayen.projectboard.repository.UserAccountRepository;
import com.laphayen.projectboard.dto.security.KakaoOAuth2Response;
import com.laphayen.projectboard.service.UserAccountService;
import org.springframework.boot.autoconfigure.security.reactive.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.SecurityFilterChain;

import java.util.UUID;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers(String.valueOf(PathRequest.toStaticResources().atCommonLocations())).permitAll()
.requestMatchers(
HttpMethod.GET,
"/",
"/articles",
"/articles/search-hashtag",
"/css/**","/scripts/**","/plugin/**","/fonts/**"
).permitAll()
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.logout(logout -> logout
.logoutSuccessUrl("/")
);
return http.build();
public SecurityFilterChain securityFilterChain(
HttpSecurity http,
OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService
) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers(String.valueOf(PathRequest.toStaticResources().atCommonLocations())).permitAll()
.requestMatchers(
HttpMethod.GET,
"/",
"/articles",
"/articles/search-hashtag",
"/css/**","/scripts/**","/plugin/**","/fonts/**"
).permitAll()
.anyRequest().authenticated()
)
.formLogin(withDefaults())
.logout(logout -> logout.logoutSuccessUrl("/"))
.oauth2Login(oAuth -> oAuth
.userInfoEndpoint(userInfo -> userInfo
.userService(oAuth2UserService)
)
)
.build();
}

@Bean
public UserDetailsService userDetailsService(UserAccountRepository userAccountRepository) {
return username -> userAccountRepository
.findById(username)
.map(UserAccountDto::from)
public UserDetailsService userDetailsService(UserAccountService userAccountService) {
return username -> userAccountService
.searchUser(username)
.map(BoardPrincipal::from)
.orElseThrow(() -> new UsernameNotFoundException("유저를 찾을 수 없습니다 - username: " + username));
}

@Bean
public OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService(
UserAccountService userAccountService,
PasswordEncoder passwordEncoder
) {
final DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();

return userRequest -> {
OAuth2User oAuth2User = delegate.loadUser(userRequest);

KakaoOAuth2Response kakaoResponse = KakaoOAuth2Response.from(oAuth2User.getAttributes());
String registrationId = userRequest.getClientRegistration().getRegistrationId();
String providerId = String.valueOf(kakaoResponse.id());
String username = registrationId + "_" + providerId;
String dummyPassword = passwordEncoder.encode("{bcrypt}" + UUID.randomUUID());

return userAccountService.searchUser(username)
.map(BoardPrincipal::from)
.orElseGet(() ->
BoardPrincipal.from(
userAccountService.saveUser(
username,
dummyPassword,
kakaoResponse.email(),
kakaoResponse.nickname(),
null
)
)
);
};

}

@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
Expand Down

0 comments on commit 9f8cbe6

Please sign in to comment.