[기술 정리] 20. 카카오 로그인 구현(2) - OIDC

KangHo Lee's avatar
Dec 11, 2024
[기술 정리] 20.  카카오 로그인 구현(2) - OIDC

OAuth로 토큰을 받고 OIDC로 인증과 인가를 하는 이유

  • OIDC는 OAuth 2.0의 확장으로, 사용자 인증과 관련된 기능을 추가합니다.
    • OAuth 2.0의 권한 부여와 OIDC의 인증을 통합하여 사용할 수 있습니다.
  • JWT를 활용한 토큰 기반 인증(Token-Based Authentication)이 가능합니다.
    • 다양한 클라이언트 유형(웹, 모바일, 데스크탑)과 호환이 가능합니다.
  • ID 토큰에 사용자 정보가 있기 때문에 요청을 2번 하지 않아도 됩니다.

ID 토큰 유효성 검증하기

1) ID 토큰

  • ID 토큰은 서비스의 로그인 세션 대신 사용할 수 있는 JSON Web Token(JWT) 형식의 토큰입니다.
  • 서비스는 ID 토큰에 포함된 사용자 인증 정보를 서비스에 활용하거나, ID 토큰의 유효성을 검증할 수 있습니다.
  • ID 토큰의 만료 시간은 액세스 토큰과 동일합니다.

2) OIDC: 공개키 목록 조회하기

notion image
  • 주의사항
    • 지나치게 빈번한 공개키 목록 조회 요청 시, 요청이 차단될 수 있습니다.
  • 공개키가 2개 있는데 kid가 일치하는 공개키를 사용하면 됩니다.
    • 공개키 타입은 RSA입니다.

3) ID 토큰의 kid 확인

  • 위 사이트에서 ID 토큰을 넣으면 확인할 수 있습니다.
notion image

4) Spring에서 ID 토큰 유효성 검증

  • 라이브러리 세팅
    • gradle
    • implementation 'com.nimbusds:nimbus-jose-jwt:9.31'
  • IdTokenTest
public class IdTokenTest { @Test public void tokenVerify_test() { String idToken = "eyJraWQiOiI5ZjI1MmRhZGQ1ZjIzM2Y5M2QyZmE1MjhkMTJmZWEiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiI3MzBhOGVjN2U5MWYwNGFiMjY0Nzk5MWVmMzRmMWY4MSIsInN1YiI6IjM4Mjc3MzEwNTgiLCJhdXRoX3RpbWUiOjE3MzM3OTE2ODEsImlzcyI6Imh0dHBzOi8va2F1dGgua2FrYW8uY29tIiwibmlja25hbWUiOiLstZzso7ztmLgiLCJleHAiOjE3MzM4MTMyODEsImlhdCI6MTczMzc5MTY4MX0.mMT4oqaT8TCnWMaKMVthpS5JdLj0itI0wn8rZm1AketyGxOYYU2fDtcVHcUvprGFgTZ3y9QCKZd6xUMtWF7eM7LgYqAhY9uY8hR_ms11tNGbWf-67j9NSJ9TpwEbTHxtLF3xjIAQOpaACRmwpqvUXn5GF_ct2ko_35LOtOOHxjGKMHs219Obb85sbEO-Rwlqi3qXEc79myfYOB1FdaOrxyG_NJtxeKHJPwzcfWo2HGdkZaf31k0XpZSYQug1yiM1L3NzVpe7_rWhg_ku_k0mp7IyS7AoLDOyceUl6kmck4XP7gVEZtKdaViVZqKA_Y6xbO7aMfNYDdnG_FaanhzBLg"; String n = "qGWf6RVzV2pM8YqJ6by5exoixIlTvdXDfYj2v7E6xkoYmesAjp_1IYL7rzhpUYqIkWX0P4wOwAsg-Ud8PcMHggfwUNPOcqgSk1hAIHr63zSlG8xatQb17q9LrWny2HWkUVEU30PxxHsLcuzmfhbRx8kOrNfJEirIuqSyWF_OBHeEgBgYjydd_c8vPo7IiH-pijZn4ZouPsEg7wtdIX3-0ZcXXDbFkaDaqClfqmVCLNBhg3DKYDQOoyWXrpFKUXUFuk2FTCqWaQJ0GniO4p_ppkYIf4zhlwUYfXZEhm8cBo6H2EgukntDbTgnoha8kNunTPekxWTDhE5wGAt6YpT4Yw"; String e = "AQAB"; BigInteger bin = new BigInteger(1, Base64.getUrlDecoder().decode(n)); BigInteger bie = new BigInteger(1, Base64.getUrlDecoder().decode(e)); RSAKey rsaKey = new RSAKey.Builder(Base64URL.encode(bin), Base64URL.encode(bie)).build(); try { // 1. 파싱 SignedJWT signedJWT = SignedJWT.parse(idToken); // 2. 검증 RSASSAVerifier verifier = new RSASSAVerifier(rsaKey.toRSAPublicKey()); if (signedJWT.verify(verifier)) { System.out.println("ID Token을 검증하였습니다"); System.out.println("Payload : " + signedJWT.getPayload()); } else { System.out.println("검증에 실패하였습니다."); } } catch (Exception ex) { ex.printStackTrace(); } } }
  • 인증 완료 시 결과
ID Token을 검증하였습니다 Payload : { "aud":"730a8ec7e91f04ab2647991ef34f1f81", "sub":"3827731058", "auth_time":1733791681, "iss":"https://kauth.kakao.com", "nickname":"닉네임", "exp":1733813281, "iat":1733791681 }
아래로 이어집니다
 
Share article

devleekangho