-
Notifications
You must be signed in to change notification settings - Fork 5
[JWT 관련]
-
카카오 인가 코드 받기
-
PuangFilm Client → Kakao Server 요청
GET https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=openid
** 이때 Redirect URI는 PuangFilm Server 주소로 설정 (Client를 거치지 않고 Server로 바로 인가 코드를 전달하기 위함)
-
카카오계정 로그인 화면 출력
-
카카오계정 로그인 로그인
-
동의 화면 출력
-
동의하고 계속하기
-
Kakao Server → PuangFilm Client 응답
302 Found Location: ${REDIRECT_URI}?code=${KAKAO_AUTHORIZE_CODE}
** 이때 Redirect URI는 PuangFilm Server 주소
https://${PUANG_FILM_SERVER_URI}/auth/login/oauth/kakao
이므로, 자동으로 2-i 요청이 이루어짐
-
-
사용자 로그인 처리
-
PuangFilm Client → PuangFilm Server 요청
GET https://${PUANG_FILM_SERVER_URI}/auth/login/oauth/kakao?code=${KAKAO_AUTHORIZE_CODE}
관련 코드) AuthController와 AuthService의 loginWithKakao()
** 실제로는 Redirect에 의해 자동으로 이루어지므로 별도 요청 필요 없음 -
PuangFilm Server → Kakao Server 요청
POST https://kauth.kakao.com/oauth/token { "grant_type" : "authorization_code", "client_id" : "${CLIENT_ID}", "redirect_uri" : "${REDIRECT_URI}", "code" : "${KAKAO_AUTHORIZE_CODE}", "client_secret" : "${CLIENT_SECRET}" }
카카오 토큰 받기 요청
관련 코드) KakaoProvier의 getTokenByCode()
-
Kakao Server → PuangFilm Server 응답
200 OK { "token_type": "bearer", "access_token": "${ACCESS_TOKEN}", "id_token": "${ID_TOKEN}", "expires_in": 7199, "refresh_token": "${REFRESH_TOKEN}", "refresh_token_expires_in": 86399, "scope": "openid profile_nickname" }
카카오 토큰 발급
** 이때 ID 토큰(
id_token
)은 JWT 형식의 토큰으로, ID 토큰의 페이로드는 다음 정보를 포함함iss: "https://kauth.kakao.com" aud: "${APP_KEY}" sub: "${USER_ID}" // kakaoId iat: 1661967952 auth_time: 1661967952 exp: 1661967972 nickname: "JordyTest"
** 주의) 위 카카오 토큰의 access_token, refresh_token은 2-vi, 2-vii에서 PuangFilm Server가 발행하는 access_token, refresh_token과 다름. <푸앙이 사진관> 로그인 상태 유지에는 후자가 사용됨.
-
ID 토큰 유효성 검증
관련 코드) OIDCProvider의 verify()
-
페이로드 검증
관련 코드) OIDCProvider의 verifyPayload()
-
iss
가https://kauth.kakao.com
와 일치하는지 -
aud
가 2-b 요청 시 사용한client_id
와 일치하는지 -
exp
가 현재 시각보다 이후인지
-
-
서명 검증
관련 코드) OIDCProvider의 verifySignature()
-
카카오 인증 서버로부터 받은 공개키 목록에서 ID 토큰의 헤더의
kid
에 해당하는 공개키 찾기
관련 코드) OIDCProvider의 getOIDCPublicKey()
**kid
는 카카오 인증 서버가 ID 토큰 서명 시 사용한 공개키 ID
** 이때 공개키 목록은 매일 새벽 5시에 조회하여 캐싱하며,kid
에 해당하는 공개키가 없을 시 카카오 인증 서버로 공개키 목록을 다시 조회하여 캐싱 업데이트.
관련 코드) KakaoProvier의 getOIDCPublicKeyList() -
위에서 얻은 공개키는 JWK 형식. JWK 공개키의 n, e값으로 RSA 공개키 생성
관련 코드) OIDCProvider의 getRSAPublicKey()
-
RSA 공개키로 서명 검증 후
sub
(kakaoId),nickname
반환
-
-
-
DB User 테이블 갱신
기존 회원) UPDATE request_date
신규 회원) INSERT
** 기존/신규 회원 여부는 kakaoId로 확인
-
JWT 형식의 refresh_token 발행 및 DB Token 테이블 갱신
refresh_token의 페이로드는 다음 정보를 포함함
iss: "https://kauth.kakao.com" sub: "${KAKAO_ID}" iat: 1661967952 // 토큰 발급 또는 갱신 시각 exp: 1661967972 // 토큰 만료 시간 userName: "JordyTest"
** 유효 기간은 1일로 설정 (논의 후 변경 가능)
-
JWT 형식의 access_token 발행
access_token의 페이로드는 다음 정보를 포함함
iss: "https://kauth.kakao.com" sub: "${KAKAO_ID}" iat: 1661967952 // 토큰 발급 또는 갱신 시각 exp: 1661967972 // 토큰 만료 시간 refreshId: "123" // refresh_token의 ID (Token 테이블의 id)
** 유효 기간은 30분으로 설정 (논의 후 변경 가능)
-
PuangFilm Server → PuangFilm Client 응답
200 OK { "access_token": "${ACCESS_TOKEN}" }
-
-
로그인
자세한 내용은 위 '카카오 로그인/회원가입 플로우' 참고
- access_token(30분), refresh_token(1일) 발급
- DB에 refresh_token 저장 (Token 테이블)
- PuangFilm Client에 access_token 전달
-
로그인된 사용자의 요청 - 토큰이 유효한 경우
-
PuangFilm Client → PuangFilm Server 요청
헤더Authorization: Bearer <access_token>
-
access_token 검증 - 유효
관련 코드) JwtProvider의 validateToken()
-
페이로드의
sub
(kakaoId)을 통해 사용자 정보 취득 후, Argument Resolver 활용하여 User 객체를 만들어 바인딩 (이 부분에 관한 설명은 Argument Resolver 구현 후 보완 예정)
-
-
로그인된 사용자의 요청 - 토큰이 만료된 경우
-
PuangFilm Client → PuangFilm Server 요청
헤더
Authorization: Bearer <access_token>
-
access_token 검증 - 만료
관련 코드) JwtProvider의 validateToken()
-
PuangFilm Server → PuangFilm Client 응답
401 Unauthorized
-
PuangFilm Client → PuangFilm Server 요청
GET https://${PUANG_FILM_SERVER_URI}/auth/reissue Authorization: Bearer <access_token>
-
access_token의 페이로드에 있는 refreshId를 이용하여 refresh_token 얻음
관련 코드) JwtProvider의 getRefreshIdFromExpiredToken()
-
refresh_token 유효기간 검증
-
reissue 처리
-
refresh_token이 유효한 경우
access_token, refresh_token 재발급 후 DB Token 테이블 업데이트
-
refresh_token이 만료된 경우
DB Token 테이블에서 해당 refresh_token 삭제
-
-
PuangFilm Server → PuangFilm Client 응답
-
refresh_token이 유효한 경우
200 OK { "access_token": "${ACCESS_TOKEN}" }
-
refresh_token이 만료된 경우
401 Unauthorized
-
-
-
로그아웃
- 별도 구현 없이 토큰이 만료되면 자동으로 로그아웃되는 방식.
- 로그아웃이 따로 없어 만료된 refresh_token이 DB에 쌓일 수 있음
- 매일 새벽 5시 5분에 DB 조회해서 만료된 refresh_token 삭제
- Issuer
-
http://www.puangfilm.com/
- 푸앙이사진관 도메인 주소
-
http://www.puangfilm.com/
- Subject
- KakaoId값
- 카카오에서 제공하는 회원번호 (식별자 역할)
- KakaoId값
- IssueAt
- 토큰 발급 시각
- Expiration
- 토큰 만료 시각
- RefreshId
- refresh_token의 ID (DB Token 테이블의 id)
- reissue에 필요
- Issuer
- Subject
- IssueAt
- Expiration
- UserName
- 사용자 닉네임
- refresh_token_id
- access_token 페이로드에 포함된 RefreshId가 이 값을 사용
- refresh_token
- kakao_id
- expiresAt