Skip to content

[JWT 관련]

tthisag246 edited this page Aug 5, 2024 · 11 revisions

카카오 로그인/회원가입 플로우

  1. 카카오 인가 코드 받기

    1. PuangFilm ClientKakao 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로 바로 인가 코드를 전달하기 위함)

    2. 카카오계정 로그인 화면 출력

    3. 카카오계정 로그인 로그인

    4. 동의 화면 출력

    5. 동의하고 계속하기

    6. Kakao ServerPuangFilm 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 요청이 이루어짐

  2. 사용자 로그인 처리

    1. PuangFilm ClientPuangFilm Server 요청

      GET https://${PUANG_FILM_SERVER_URI}/auth/login/oauth/kakao?code=${KAKAO_AUTHORIZE_CODE}

      관련 코드) AuthController와 AuthService의 loginWithKakao()

    2. PuangFilm ServerKakao 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()

    3. Kakao ServerPuangFilm 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과 다름. <푸앙이 사진관> 로그인 상태 유지에는 후자가 사용됨.

    4. ID 토큰 유효성 검증

      관련 코드) OIDCProvider의 verify()

      1. 페이로드 검증

        관련 코드) OIDCProvider의 verifyPayload()

        • isshttps://kauth.kakao.com와 일치하는지
        • aud가 2-b 요청 시 사용한 client_id와 일치하는지
        • exp가 현재 시각보다 이후인지
      2. 서명 검증

        관련 코드) OIDCProvider의 verifySignature()

        • 카카오 인증 서버로부터 받은 공개키 목록에서 ID 토큰의 헤더의 kid에 해당하는 공개키 찾기
          관련 코드) OIDCProvider의 getOIDCPublicKey()
          ** kid는 카카오 인증 서버가 ID 토큰 서명 시 사용한 공개키 ID
          ** 이때 공개키 목록은 매일 새벽 5시에 조회하여 캐싱하며, kid에 해당하는 공개키가 없을 시 카카오 인증 서버로 공개키 목록을 다시 조회하여 캐싱 업데이트.
          관련 코드) KakaoProvier의 getOIDCPublicKeyList()

        • 위에서 얻은 공개키는 JWK 형식. JWK 공개키의 n, e값으로 RSA 공개키 생성

          관련 코드) OIDCProvider의 getRSAPublicKey()

        • RSA 공개키로 서명 검증 후 sub(kakaoId), nickname 반환

    5. DB User 테이블 갱신

      기존 회원) UPDATE request_date

      신규 회원) INSERT

      ** 기존/신규 회원 여부는 kakaoId로 확인

    6. JWT 형식의 refresh_token 발행 및 DB Token 테이블 갱신

      refresh_token의 페이로드는 다음 정보를 포함함

      iss: "https://kauth.kakao.com"
      sub: "${KAKAO_ID}"
      iat: 1661967952 // 토큰 발급 또는 갱신 시각
      exp: 1661967972 // 토큰 만료 시간
      userName: "JordyTest"
      

      ** 유효 기간은 1일로 설정 (논의 후 변경 가능)

    7. 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분으로 설정 (논의 후 변경 가능)

    8. PuangFilm ServerPuangFilm Client 응답

      200 OK
      {
          "access_token": "${ACCESS_TOKEN}"
      }
      
Clone this wiki locally