๐Ÿช†

๋กœ๊ทธ์ธ ๊ฐœ์„ 

์ž‘์„ฑ์ž
ํƒœ๊ทธ
Dev
์†์„ฑ
Aug 5, 2022 08:20 PM
 

1. ํ˜„์žฌ ๋กœ๊ทธ์ธ ์ฝ”๋“œ ๋ถ„์„ ๋ฐ ๋ฌธ์ œ์ 

 
ํ˜„์žฌ ๊ตฌ๊ธ€ ์†Œ์…œ ๋กœ๊ทธ์ธ ์ฝ”๋“œ ํ๋ฆ„
 
ํ”„๋ก ํŠธ์—์„œ ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ url ์š”์ฒญ http://localhost:8080/oath2/authorization/google โ†’
๊ตฌ๊ธ€ ์ธ์ฆ ์„œ๋ฒ„ ์ธ์ฆ โ†’ ๊ตฌ๊ธ€ ๋ฆฌ์†Œ์Šค ์„œ๋ฒ„ ์ ‘๊ทผ โ†’ ์œ ์ € ์ •๋ณด ์ €์žฅ ๋ฐ ํ† ํฐ ์ƒ์„ฑ โ†’ ํ† ํฐ์€ redirect URL์— Query String์œผ๋กœ ๋ฐœ๊ธ‰
 
ํ˜„์žฌ redirectUrl์€ bidmarket.vercel.app/auth?token=~~ ์œผ๋กœ ํ•˜๋“œ์ฝ”๋”ฉ ๋˜์–ด์žˆ๋Š”์ƒํƒœ
 
  • ํ˜„์žฌ ์ƒํ™ฉ์—์„œ ํ† ํฐ์„ ์ฟ ํ‚ค์— http only ์˜ต์…˜์„ ์ค˜์„œ ์ €์žฅํ•˜๊ณ  ๋ฉ”์ธํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์‹œ์ผœ์ฃผ๊ณ  ์‹ถ์Œ
  • ์šฐ์„  ํ˜„์žฌ ์ฝ”๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํŒŒ์•… ํ• ๊ฒƒ์ž„
 

ํ˜„์žฌ security ์ฝ”๋“œ ๋ถ„์„

WebSecurityConfig ํŒŒ์ผ
@Configuration @EnableWebSecurity public class WebSecurityConfig { ...์ƒ๋žต @Bean public SecurityFilterChain filterChain(Jwt jwt, HttpSecurity http, OAuth2AuthorizedClientRepository repository, OAuth2AuthenticationSuccessHandler handler ) throws Exception { http.authorizeRequests() ...์ƒ๋žต /** * OAuth2 ์„ค์ • */ .oauth2Login() .authorizationEndpoint() .authorizationRequestRepository(authorizationRequestRepository()) .and() .successHandler(handler) .authorizedClientRepository(repository) .and() ...์ƒ๋žต return http.build(); } }
OAuth2AuthenticationSuccessHandler ํŒŒ์ผ
package com.saiko.bidmarket.common.oauth2; import java.io.IOException; import java.nio.charset.StandardCharsets; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import com.saiko.bidmarket.common.jwt.Jwt; import com.saiko.bidmarket.user.entity.User; import com.saiko.bidmarket.user.service.UserService; public class OAuth2AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { private final Logger log = LoggerFactory.getLogger(this.getClass()); private final Jwt jwt; private final UserService userService; public OAuth2AuthenticationSuccessHandler(Jwt jwt, UserService userService) { this.jwt = jwt; this.userService = userService; } @Override public void onAuthenticationSuccess( HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { if (authentication instanceof OAuth2AuthenticationToken) { OAuth2AuthenticationToken oauth2Token = (OAuth2AuthenticationToken)authentication; OAuth2User principal = oauth2Token.getPrincipal(); log.debug("Message {}, {}", principal.getName(), principal.getAttributes()); String registrationId = oauth2Token.getAuthorizedClientRegistrationId(); User user = processUserOAuth2UserJoin(principal, registrationId); String loginSuccessJson = generateLoginSuccessJson(user); response.setContentType("application/json;charset=UTF-8"); response.setContentLength(loginSuccessJson.getBytes(StandardCharsets.UTF_8).length); response.sendRedirect("http://localhost:3000/auth?" + loginSuccessJson); } } private User processUserOAuth2UserJoin(OAuth2User oAuth2User, String registrationId) { return userService.join(oAuth2User, registrationId); } private String generateLoginSuccessJson(User user) { String token = generateToken(user); log.debug("Jwt({}) created for oauth2 login user {}", token, user.getId()); return "token=" + token; } private String generateToken(User user) { return jwt.sign(Jwt.Claims.from(user.getId(), new String[]{"ROLE_USER"})); } }
 
  1. ๋กœ๊ทธ์ธ ์š”์ฒญ URL http://localhost:8080/oauth2/authorization/google
 
HttpCookieOAuth2AuthorizationRequestRepository ์— ๊ฑธ๋ฆฐ ๋””๋ฒ„๊ทธ
notion image
notion image
notion image
 
 
 
  • authorization_uri = https://accounts.google.com/o/oauth2/v2/auth
  • redirect_uri = http://localhost:8080/login/oauth2/code/google
AUTHORIZATION_REQUEST ์ฟ ํ‚ค ์ƒ์„ฑ
๊ตฌ๊ธ€ ์„œ๋ฒ„์— AUTHORIZATION_CODE๋ฅผ ์š”์ฒญํ•˜๋Š” ์ฟ ํ‚ค๋ฅผ ์ƒ์„ฑ
notion image
 
 
์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์™€ OAuth 2.0์œผ๋กœ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„
์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ(Spring Security)๋Š” ๋ง‰๊ฐ•ํ•œ ์ธ์ฆ๊ณผ ์ธ๊ณผ(ํ˜น์ธ ๊ถŒํ•œ ๋ถ€์—ฌ) ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. ์‚ฌ์‹ค์ƒ ์Šคํ”„๋ง ๊ธฐ๋ฐ˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ๋ณด์•ˆ์„ ์œ„ํ•œ ํ‘œ์ค€์ด๋ผ๊ณ  ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค. ํ•„ํ„ฐ ๊ธฐ๋ฐ˜์˜ ๋ณด์•ˆ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์„ ์ ๊ทน์ ์œผ๋กœ ๊ถŒํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. OAuth ํ•˜์ง€๋งŒ ์˜คํ”ˆ ์•„์ด๋””๋Š” ํ‘œ์ค€์ŠคํŽ™์ด ์กด์žฌํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ œ๊ณต์ž๋งˆ๋‹ค ์„œ๋กœ ๋‹ค๋ฅธ ํ”„๋กœํ† ์ฝœ์„ ์ œ๊ณตํ•˜์—ฌ ์—ฌ๋Ÿฌ ์˜คํ”ˆ ์•„์ด๋””๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด์„  ๊ฐ ๊ทœ๊ฒฉ๋ณ„๋กœ ์—ฐ๋™์„ ๋งŒ๋“ค์–ด์•ผ ํ–ˆ๊ณ , ์ผ๋ถ€ ํ”„๋กœํ† ์ฝœ์—์„  ๋ณด์•ˆ ์ด์Šˆ๊ฐ€ ๋งŽ์ด ๋‚˜์˜ค๊ธฐ๋„ ํ–ˆ์Šต๋‹ˆ๋‹ค.
์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์™€ OAuth 2.0์œผ๋กœ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„