카카오 간편 로그인을 JWT + OAuth2 + Spring Security + Redis로 구현해보기 #14
RTUnu12
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
02.08 변경점
프론트엔드 분들을 위한 바닐라 React 코드
https://reevserver.site/api/v1/auth/oauth2/kakao
으로 요청.https://reevserver.site/api/v1/auth/reissue
로 RT 재발급 요청https://reevserver.site/api/v1/logout
요청 시 Cookie 안에 저장된 RT 삭제 (AT도 삭제되어야 함)https://reevserver.site/api/v1/auth/oauth2/kakao?redirect=/custom-page
로 redirect 파라미터를 붙여서 요청 시https://example.com/login/success?redirect=/custom-page
로 리다이렉트바닐라 React 코드
실행 영상
2025-01-28.172523.online-video-cutter.com.mp4
OAuth2란?
요즘 웹사이트를 보면 다음과 같이 ##로 시작하기라는 로그인 옵션이 존재합니다. 이 기능을 통해 클릭 단 한번으로 로그인을 간편하게 할 수 있게 하는 것 뿐만 아니라, 연동되는 외부 웹 애플리케이션에서 Google 등이 제공하는 기능을 간편하게 사용할 수 있다는 장점이 있습니다.
OAuth2는 사용자가 자신의 자격증명을 서비스 제공자에게 직접 공유하지 않고도, 제3자 애플리케이션에 안전하게 접근 권한을 부여할 수 있는 인증 및 권한 부여 프로토콜로, 오늘날 웹과 모바일 애플리케이션에서 필수적인 기술로 자리 잡고 있습니다.
OAuth2의 주요 원리 중 하나는 권한 위임입니다. 사용자는 신뢰할 수 있는 인증 제공자(Google, Facebook 등)를 통해 본인의 신원을 확인하고, 제3자 애플리케이션이 자신의 데이터를 일정 범위 내에서 접근할 수 있도록 허가합니다. 이 과정에서 애플리케이션은 액세스 토큰을 받아 이를 통해 데이터에 접근하며, 사용자의 비밀번호나 민감한 정보를 직접 다루지 않기 때문에 보안성을 높입니다.
주요 구성 요소는 다음과 같습니다.
Resource Owner
Client
Authorization Server
Resource Server
Access Token
Refresh Token
하지만 Refresh Token이 존재한다면 Access Token 만료 시 Refresh Token을 통해 Access Token을 재발급받아 재로그인의 필요가 없습니다.
위 구성 요소를 통해 사용자의 OAuth2 로그인 흐름과 API 호출까지의 과정을 그림으로 그려보면 다음과 같습니다.

그림 상으로 보면 복잡하지만 정말 간단히 요약하자면 다음과 같습니다.
관련 코드
build.gradle
Member.java
OAuth2User의 구현체입니다. 저희가 사용할 엔티티입니다.
CustomOAuth2UserService.java
Member의 내용을 채우기 위해 Kakao로부터 온 JSON을 매핑하는 서비스입니다. Spring Security의 설정 파일인 SecurityConfig에서 OAuth2 서비스로 지정됩니다.
AuthController.java
로그인, 로그아웃 외 RT 재발급, AT로 현재 로그인 상태 확인을 할 수 있습니다.
RefreshTokenService.java
RefreshToken을 Redis에 저장/삭제하고 RT를 만드거나 그대로 사용하는 서비스입니다. Redis에 대해서는 나중에 서술합니다.
JWT
JWT(JSON Web Token)는 JSON 기반의 토큰으로, 클라이언트와 서버 간에 정보를 안전하게 전달하기 위해 사용됩니다. 주로 인증과 권한 부여를 위해 활용되며, 세션을 대체할 수 있는 유용한 방법입니다.
주요 특징
동작 원리
JWT에는
userId
가 포함되며, 이 정보는 Access Token과 Refresh Token 역할을 합니다. 서버는 Redis에userId:RefreshToken
형식으로 Refresh Token을 저장합니다. Refresh Token이 탈취되더라도 Redis의 값을 비교하여 현재 재발급된 Refresh Token과 다르다면 탈취 사실을 확인할 수 있습니다.관련 코드
JwtProvider.java
JWT를 만들고 검증하는 곳입니다.
application.properties에서 값을 찾아와서 생성하고 검증하는 것을 볼 수 있습니다.
일단 AT, RT 둘 다 만료 기간은 3일로 잡았습니다.
Key는 application.properties를 통해서 만들어지고, 이를 이용해 암호화/복호화합니다.
Spring Security
Spring Security는 Spring Framework 기반 애플리케이션의 보안을 담당하는 모듈로, 인증(Authentication)과 권한 부여(Authorization) 기능을 제공합니다.
주요 특징
주요 구성 요소
@AuthenticationPrincipal Long userId
를 통해서 불러옵니다.관련 코드
JwtAuthenticationFilter.java
OncePerRequestFilter의 구현체이고, 즉 커스텀 필터입니다. Spring Security에서 본 작업을 수행하기 전에 이 필터를 가져와서 JWT 내용을 JwtProvider로 추출/검증하고, 이후 SecurityContext에 사용자 정보(userId)를 저장합니다.
OAuth2SuccessHandler.java
로그인이 성공하였을 경우 실행되는 핸들러입니다. Redis에 RT를 저장, 이후 프론트엔드에게 쿠키와 헤더를 전달하고 프론트엔드의 주소로 리다이렉트시킵니다.
OAuth2FailureHandler.java
로그인이 실패할 경우 실행되는 핸들러입니다. 실패를 가리키는 주소로 리다이렉트시킵니다.
OAuth2LogoutHandler.java
로그아웃 시 실행되는 핸들러입니다. Redis에 RT를 삭제하고 이 때 쿠키도 같이 삭제합니다.
CustomAuthorizationRequestResolver.java
OAuth2 로그인 시 Authorization Request를 커스터마이징하는 역할을 수행합니다.
사용자가 /api/v1/auth/oauth2를 통해 OAuth2 로그인을 시도할 때, 추가적인 쿼리 파라미터(예: redirect)를 처리합니다.
redirect 쿼리 파라미터를 읽어 세션에 저장하며, 이후 인증이 완료된 후 사용자 리다이렉션에 활용됩니다.
즉, 요청에 redirect 쿼리 파라미터가 포함되어 있으면 이를 세션에 저장하여 이후 사용(예: 로그인 성공 후 리다이렉션)할 수 있도록 합니다.
지금 상황에서 당장은 필요없지만, 프론트엔드에서 현재 상황으로 다시 리다이렉트를 원할 경우 사용이 가능합니다.
GET http://서버주소/api/v1/auth/oauth2/kakao?redirect=/custom-page
로 호출을 수행하면
https://example.com/login/success?redirect=/custom-page
로 리다이렉트 되는 구조입니다.
FailedAuthenticationEntryPoint.java
로그인에 실패할 경우 백엔드 서버에서 볼 수 있는 페이지입니다. 지금 당장은 필요없지만 후에 사용이 가능합니다.
SecurityConfig.java
Spring Security의 설정 파일이며, 위에서 만들어 두었던 모든 구현체들을 설정에 등록합니다.
그 외, CORS 설정이나 엔드포인트 접근 제한(로그인 한 사람들 중 ROLE_ADMIN만 볼 수 있는 페이지, 지금은 임시로 전부 풀어둠) 등을 수행할 수 있습니다.
Redis
Redis는 오픈 소스 인메모리 데이터베이스로, 빠른 데이터 처리를 위해 자주 사용됩니다. 주로 캐싱, 세션 관리, 메시지 브로커 등으로 활용됩니다.
Redis와 Refresh Token 관리
userId:RefreshToken
형식으로 데이터를 저장합니다.userId
의 Refresh Token을 삭제합니다.관련 코드
RedisRepository.java
Redis에서 찾기, 생성 및 수정, 삭제를 구현한 리포지토리입니다. JPA를 사용하지 않고 RedisTemplate를 사용합니다.
RedisConfig.java
Redis의 설정파일입니다.
전체적인 흐름
/api/v1/auth/oauth2/kakao
엔드포인트를 통해 로그인합니다.userId:RefreshToken
형식으로 저장됩니다./api/v1/auth/reissue
엔드포인트를 통해 RT를 사용하여 새로운 AT를 발급받습니다./api/v1/logout
엔드포인트를 호출하여 Redis에서 RT를 삭제하고 쿠키의 RT를 제거합니다.위의 흐름을 통해 AT 및 RT를 안전하게 관리하며 인증 및 권한 부여를 수행합니다.
Beta Was this translation helpful? Give feedback.
All reactions