[Spring] 소셜 로그인 후 토큰 전달

icebox127·2026년 1월 18일

TO:DAY 서버

목록 보기
6/8

배경

이메일 로그인 성공
→ accessToken, refreshToken: responseBody로 전달
소셜 로그인 성공
→ OAuth2SuccessHandler
→ accessToken: redirect query
→ refreshToken: cookie 저장

이메일을 통한 회원가입에선 응답 데이터로 accessToken, refreshToken을 전달했다. 소셜 로그인은 Spring Security를 이용하기 때문에 응답 데이터로 전달하기 어려웠다. 그래서 로그인 후 프론트로 리다이렉트할 때 쿼리 파라미터로 accessToken을 전달했다.

하지만 쿼리 파라미터로 전달할 시 보안에 취약하다는 단점이 있다. 1시간 단위로 만료되는 accessToken과 달리 refreshToken은 보안에 더 신경써야해서 쿠키를 사용했다.

구현 과정

1. CookieUtil

쿠키를 생성/삭제하는 로직을 담은 CookieUtil을 생성한다.

public class CookieUtil {
    public static void addCookie(HttpServletResponse response, String name, String value, int maxAge){
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        cookie.setMaxAge(maxAge);
        response.addCookie(cookie);
    }

    public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String name){
        Cookie[] cookies = request.getCookies();
        if (cookies== null) return;
        for (Cookie cookie: cookies){
            if (name.equals(cookie.getName())){
                cookie.setValue("");
                cookie.setPath("/");
                cookie.setMaxAge(0);
                response.addCookie(cookie);
            }
        }
    }

}
  • setPath: 경로 설정 ("/"로 설정하면 해당 도메인의 모든 경로에서 쿠키 접근 가능)
  • setMaxAge: 쿠키 만료 시간 (리프레시 토큰 만료 시간과 같게 생성)

2. Controller 구현

@PostMapping("/auth/logout")
    public ApiResponse<Void> logout(@Valid @RequestBody TokenReissueDto dto,
                                    HttpServletRequest request, HttpServletResponse response){
        tokenService.logout(dto);
        CookieUtil.deleteCookie(request, response, "refreshToken");
        return ApiResponse.success(null);
    }

"/logout"은 Spring Security가 예약해 둔 엔드포인트여서 "/auth/logout"으로 했다. 소셜 로그인의 경우 쿠키에도 refreshToken을 저장하므로, 컨트롤러에서 삭제해준다.

3. Service 구현

public void logout(TokenReissueDto dto){
        String refreshTokenValue = dto.getRefreshToken();
        RefreshToken refreshToken = refreshTokenRepository.findByRefreshToken(refreshTokenValue)
                .orElseThrow(() -> new AuthException(AuthErrorCode.TOKEN_NOT_FOUND));
        refreshTokenRepository.delete(refreshToken);
    }

db에 저장된 refreshToken값을 삭제한다.

accessToken의 경우 db에 저장하지 않고 발급 즉시 프론트로 전달하여 프론트 localStorage에 저장되기에, 프론트 측에서 삭제하는 것으로 구현했다.

profile
감자의 공부기록🥔

0개의 댓글