Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] feat: OpenID Connect 방식의 인증 기능 추가 (#909) #910

Merged
merged 6 commits into from
Apr 30, 2024

Conversation

seokjin8678
Copy link
Collaborator

📌 관련 이슈

✨ PR 세부 내용

OpenID Connect 방식의 인증 기능을 추가했습니다.

사용자는 OAuth2로 인증을 수행하고, accessToken을 서버로 보내지 않고 idToken을 서버로 보냅니다.

idToken은 JWT 토큰 형식으로, 모든 정보가 노출되어 있는데, 이걸로 어떻게 신원을 검사하냐면, OAuth2 서버에서 비밀키로 서명된 JWT 토큰을 OAuth2 서버에 공개키를 요청하여, 서버에서 해당 공개키로 IdToken이 수정되지 않은 토큰임을 검사합니다.

따라서 악의적으로 토큰을 수정해서 보내더라도, 서버에서 해당 토큰이 수정되었는지 판단할 수 있으므로 보안에 문제가 없습니다!

카카오에서 제공하는 OpenID 유효성 검증 절차는 다음과 같습니다.


  1. ID 토큰의 영역 구분자인 온점(.)을 기준으로 헤더, 페이로드, 서명을 분리
  2. 페이로드를 Base64 방식으로 디코딩
  3. 페이로드의 iss 값이 https://kauth.kakao.com와 일치하는지 확인
  4. 페이로드의 aud 값이 서비스 앱 키와 일치하는지 확인
  5. 페이로드의 exp 값이 현재 UNIX 타임스탬프(Timestamp)보다 큰 값인지 확인(ID 토큰이 만료되지 않았는지 확인)
  6. 페이로드의 nonce 값이 카카오 로그인 요청 시 전달한 값과 일치하는지 확인
  7. 서명 검증

서명 검증은 다음 순서로 진행합니다.

  1. 헤더를 Base64 방식으로 디코딩
  2. OIDC: 공개키 목록 조회하기를 통해 카카오 인증 서버가 서명 시 사용하는 공개키 목록 조회
  3. 공개키 목록에서 헤더의 kid에 해당하는 공개키 값 확인
    3.1 공개키는 일정 기간 캐싱(Caching)하여 사용할 것을 권장하며, 지나치게 빈번한 요청 시 요청이 차단될 수 있으므로 유의
  4. JWT 서명 검증을 지원하는 라이브러리를 사용해 공개키로 서명 검증
    5.1 참고: OpenID Foundation, jwt.io
    5.2 라이브러리를 사용하지 않고 직접 서명 검증 구현 시, RFC7515 규격에 따라 서명 검증 과정 진행 가능

여기서 3, 4, 5, 6, 서명 검증 과정은 KakaoOpenIdUserInfoProvider에 구현되어 있으니 참고하시면 될 것 같습니다.
(6 과정은 시간 상의 이유로 생략했습니다. 추후 구현이 필요합니다)

서명 검증을 진행할 때, 공개키 목록을 매번 조회하면 요청이 차단될 수 있으므로 CachedOpenIdKeyProvider를 통해 캐싱을 하였습니다.
라이브러리 캐시를 사용한 것이 아닌, 직접 캐시를 구현하여 동시성 문제를 처리하는 코드가 포함되어 있으므로 약간 지저분 합니다. 😂
ConcurrentHashMap을 사용하는 방법도 있는데, computeIfAbsent의 2번째 매개변수인 매핑 함수에 현재 상태를 변경하면 안 된다는 규칙이 있어서, 직접 동시성 문제를 처리할 수 밖에 없었네요. 😂

@seokjin8678 seokjin8678 added BE 백엔드에 관련된 작업 📬 API API가 변경되거나 추가되는 작업 🏗️ 기능 기능 추가에 관한 작업 labels Apr 29, 2024
@seokjin8678 seokjin8678 self-assigned this Apr 29, 2024
@github-actions github-actions bot requested review from BGuga, carsago and xxeol2 April 29, 2024 10:36
Copy link

github-actions bot commented Apr 29, 2024

Test Results

219 files  219 suites   26s ⏱️
714 tests 714 ✅ 0 💤 0 ❌
727 runs  727 ✅ 0 💤 0 ❌

Results for commit 59b8911.

♻️ This comment has been updated with latest results.

oAuth2OpenIdClients -> openIdClients
Copy link
Member

@BGuga BGuga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다 설명이 친절해서 이해하기 수월했네요

ConcurrentHashMap을 사용하는 방법도 있는데, computeIfAbsent의 2번째 매개변수인 매핑 함수에 현재 상태를 변경하면 안 된다는 규칙이 있어서, 직접 동시성 문제를 처리할 수 밖에 없었네요. 😂

해당 규칙의 출처를 알 수 있을까요??

@seokjin8678
Copy link
Collaborator Author

수고하셨습니다 설명이 친절해서 이해하기 수월했네요

ConcurrentHashMap을 사용하는 방법도 있는데, computeIfAbsent의 2번째 매개변수인 매핑 함수에 현재 상태를 변경하면 안 된다는 규칙이 있어서, 직접 동시성 문제를 처리할 수 밖에 없었네요. 😂

해당 규칙의 출처를 알 수 있을까요??

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#computeIfAbsent-K-java.util.function.Function-

해당 Javadoc에 나와 있습니다!

@seokjin8678
Copy link
Collaborator Author

클라이언트에서 인증 기능을 사용해야 하므로, 머지하도록 하겠습니다!
어제 말한것 처럼 추가적인 의견 있으시면 새로운 이슈로 부탁드립니다!

@seokjin8678 seokjin8678 merged commit 5087504 into dev Apr 30, 2024
3 checks passed
@seokjin8678 seokjin8678 deleted the feat/#909 branch April 30, 2024 10:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BE 백엔드에 관련된 작업 🏗️ 기능 기능 추가에 관한 작업 📬 API API가 변경되거나 추가되는 작업
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BE] OpenID Connect 방식의 인증을 구현한다.
2 participants