feat(auth): 구글·Apple 로그인 서버 구현 - #18
Merged
Merged
Conversation
카카오만 있던 소셜 로그인에 구글·Apple 을 붙인다. 앱 연결은 Apple 개발자 계정이 나온 뒤라 서버만 먼저 끝내둔다. ## 자격증명 종류가 제공자마다 다르다 카카오 access_token — 제공자 API 에 되물어 소유자 확인 (기존) 구글·Apple id_token(JWT) — 제공자 공개키(JWKS)로 서명 검증 Apple 은 프로필 조회 API 자체가 없어서 토큰 검증 외에 방법이 없다. 인터페이스는 fetch(String) 그대로 두고 파라미터 의미만 문서화했다. ## aud 검증이 핵심이다 서명과 만료만 보면 다른 앱이 같은 제공자에서 받은 토큰으로도 로그인이 된다. 우리 클라이언트 ID 로 발급된 토큰인지 반드시 확인해야 한다. audiences 설정이 비어 있으면 조용히 통과시키지 않고 로그인을 거부한다. 설정 누락이 보안 구멍으로 이어지지 않게 하려는 것이다. 서버는 정상 기동하고 해당 제공자만 막힌다. JWKS 처리는 NimbusJwtDecoder 에 맡겼다. 직접 짜면 키 회전과 alg 혼동 공격 (RS256 을 none/HS256 으로 바꿔치기)을 놓치기 쉽다. ## Apple 은 이름을 최초 1회만 준다 identity token 에는 이름이 없고 최초 인증 응답에서만 한 번 온다. 두 번째 로그인부터는 어떤 경로로도 못 받는다. 그래서 요청에 displayName 을 선택 항목으로 받아 가입 시 표시 이름의 기본값으로만 쓴다 — 클라이언트가 보낸 값이라 신원 판단에는 쓰지 않는다. ## 이메일 구글·Apple 모두 email_verified 가 참일 때만 이메일을 채운다. 미검증 이메일을 받으면 남의 이메일로 가입하는 경로가 열린다. Apple 은 이 값을 문자열 "true" 로 줄 때가 있어 양쪽을 본다. ## 테스트 JWKS 를 흉내내는 서버를 JDK 내장 HttpServer 로 띄우고 직접 서명한 토큰으로 검증한다. 정상 통과 · 다른 앱 aud · 다른 발급자 · 만료 · 서명 불일치 · 미설정 6가지.
OAUTH_GOOGLE_AUDIENCES / OAUTH_APPLE_AUDIENCES. 구글은 클라이언트 라이브러리 설정에 따라 id_token 의 aud 가 web 인지 iOS 인지 갈린다. 둘 다 넣어두면 어느 쪽이든 통과한다. 비어 있으면 해당 제공자 로그인이 거부된다. 조용히 통과시키면 다른 앱의 토큰으로도 로그인이 되기 때문에, 설정 누락을 실패로 드러내는 쪽을 택했다.
likell1
added a commit
that referenced
this pull request
Aug 20, 2026
feat(auth): 구글·Apple 로그인 서버 구현
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
카카오만 있던 소셜 로그인에 구글·Apple 을 붙입니다. 앱 연결은 Apple 개발자 계정이
나온 뒤라 서버만 먼저 끝냅니다.
자격증명 종류가 제공자마다 다르다
Apple 은 프로필 조회 API 자체가 없어 토큰 검증 외에 방법이 없습니다.
인터페이스는
fetch(String)그대로 두고 파라미터 의미만 문서화했습니다.aud 검증이 핵심
서명과 만료만 보면 다른 앱이 같은 제공자에서 받은 토큰으로도 로그인이 됩니다.
우리 클라이언트 ID 로 발급된 토큰인지 확인해야 막힙니다.
audiences가 비어 있으면 조용히 통과시키지 않고 로그인을 거부합니다. 설정누락이 보안 구멍으로 이어지지 않게 하려는 것입니다. 서버는 정상 기동하고 해당
제공자만 막힙니다.
JWKS 처리는
NimbusJwtDecoder에 맡겼습니다. 직접 짜면 키 회전과 alg 혼동공격(RS256 을 none/HS256 으로 바꿔치기)을 놓치기 쉽습니다.
Apple 은 이름을 최초 1회만 준다
identity token 에 이름이 없고 최초 인증 응답에서만 한 번 옵니다. 두 번째
로그인부터는 어떤 경로로도 못 받습니다. 요청에
displayName을 선택 항목으로 받아가입 시 표시 이름의 기본값으로만 씁니다 — 클라이언트가 보낸 값이라 신원 판단에는
쓰지 않습니다.
이메일
구글·Apple 모두
email_verified가 참일 때만 이메일을 채웁니다. 미검증 이메일을받으면 남의 이메일로 가입하는 경로가 열립니다. Apple 은 이 값을 문자열
"true"로줄 때가 있어 양쪽을 봅니다.
카카오 이메일은 비즈 앱 전환이 필요해 지금은 못 받습니다. 서버가 이미 이메일 없는
경우를 처리하므로 코드 변경 없이 나중에 켜면 됩니다.
테스트
JWKS 를 흉내내는 서버를 JDK 내장
HttpServer로 띄우고 직접 서명한 토큰으로검증합니다. 정상 통과 · 다른 앱 aud · 다른 발급자 · 만료 · 서명 불일치 · 미설정
6가지.
./gradlew build통과.배포
운영
.env에OAUTH_GOOGLE_AUDIENCES(웹+iOS 클라이언트 ID)와OAUTH_APPLE_AUDIENCES=com.purut를 이미 넣어뒀습니다.