OAuth2.0과 JWT적용 - 3
처음 들어오는 사용자가 OAuth로그인 후 -> 처음 들어오는 사용자면 DB에 정보 저장후 -> 토큰 발급
이러한 로직을 수행하려고 한다.
우선 Controller를 먼저 구성해보자
@RestController
@RequiredArgsConstructor
public class MemberController {
private final OAuthService oAuthService;
@GetMapping("/oauth/login")
public ResponseEntity<Token> loginController(@AuthenticationPrincipal OAuth2User oAuth2User) {
return ResponseEntity.ok(oAuthService.login(oAuth2User.getAttributes()));
}
}
return되는 저것은 우선 신경쓰지 말자.
전에 구성했던 OAuthUserService를이용해 loadUser로 대항 OAuth인증을 하는 사용자 정보를 가지고 온다.
(https://winwin-k9.tistory.com/106 이전글은 여기 참고)
스프링 시큐리티는 SecurityContext에 인증된 Authentication 객체를 넣어두고 현재 스레드 내에서 공유되도록 관리한다.
OAuthService
@Service
@RequiredArgsConstructor
public class OAuthService {
private final MemberRepository memberRepository;
private final TokenService tokenService;
@Transactional
public Token login(Map<String, Object> attribute) {
String email = (String) attribute.get("email");
String name = (String) attribute.get("name");
if (memberRepository.findByEmail(email) == null) {
Member member = new Member(email, name);
memberRepository.save(member);
}
return tokenService.generateToken(email, name);
}
}
OAuth인증 사용자로 부터 Attribute를 가져온다. 인증된 사용자의 Attribute는 속성으로 Map구조로 되어있다.
이 정보를 받아서 해당 유저가 DB에 이미 저장이 되어있지 않으면 정보를 저장(회원가입 처리)후
토큰을 발급해주도록 한다.
다음은 Security설정이다.
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final OAuthUserService oAuthUserService;
private final JwtFilter jwtFilter;
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable()
.authorizeHttpRequests().anyRequest().permitAll()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) //세션사용 안함
.and()
.formLogin()
.and()
.oauth2Login() //OAuthLogin 설정
.userInfoEndpoint() // oauth2Login 설정을 시작
.userService(oAuthUserService) // 로그인을 oAuthUserService에서 처리
.and()
.defaultSuccessUrl("/oauth/login");
http.addFilter(jwtFilter);
return http.build();
}
}
OAuth로그인이 끝나면 url이 defaultSuccessUrl인 /oauth/login 으로 이동하게 된다.
여기서 오류가 발생하는데
does not have a registered order and cannot be added without a specified order
addFilter는 메서드를 사용하기 위해서는 반드시 Spring Security Framework 에서 제공되는 필터 혹은 이를 확장한 객체이어야 한다.
따라서 addFilterBefore나 After를 사용해야 한다.
따라서 다음과 같이 변경해야 한다.
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
UsernamePasswordAuthenticationFilter는 Form인증을 처리하는 필터이다.
사용자가 로그인하면 인증처리가 이루어지는데, 이 인증처리를 담당하고 관련된 요청을 처리한다.
http://localhost:8080/oauth2/authorization/google
OAuth인증을 하는 해당 URL로 접속후, 로그인을 하면
아래와 같이 토큰을 발급받는것을 확인할 수 있다.