-
Notifications
You must be signed in to change notification settings - Fork 0
Frontend Apple Login Guide
상태: 리뷰 중 — 앱 PR #164(이슈 #163) / 웹 PR #166(이슈 #165) 왜: App Store 심사 지침 4.8 — 카카오 로그인을 제공하는 앱은 Sign in with Apple도 함께 제공해야 심사를 통과합니다. 범위: iOS 앱(1~5절)과 웹(6절) 둘 다 지원합니다. 웹 로그인은 PR #166(이슈 #165)에서 추가됐습니다.
- Base URL:
https://api.ditto.pics - 헤더:
X-API-Key: <키>—Authorization은 필요 없습니다(로그인 전 호출) - 응답 래핑: HTTP는 항상 200, 성공/실패는
success로 구분
POST /api/v1/users/social-login/apple/native
Content-Type: application/json
{
"identityToken": "eyJraWQiOi...", // 필수
"rawNonce": "a1b2c3...", // 선택(권장)
"name": "김철수" // 선택(최초 1회만)
}
응답과 Set-Cookie(refreshToken)는 카카오 네이티브 로그인과 완전히 같습니다.
카카오와 같은 타입을 그대로 재사용하면 됩니다. 분기 처리도 동일합니다 — sanctioned 먼저 보고, 아니면 signupRequired로 회원가입 화면 여부를 정합니다.
@capacitor-community/apple-sign-in(또는 ASAuthorizationAppleIDProvider)에서:
| 서버 필드 | 앱에서 | 비고 |
|---|---|---|
identityToken |
response.identityToken |
애플이 서명한 JWT. 이것만으로 인증이 끝납니다 |
rawNonce |
앱이 만든 원본 nonce | 애플 요청에는 sha256(rawNonce)를 넣고, 서버에는 원본을 보냅니다 |
name |
response.givenName·familyName
|
authorizationCode는 서버로 보내지 않아도 됩니다. 서버가 인가 코드 교환을 하지 않기 때문입니다.
애플은 사용자가 처음 이 앱에 로그인을 허용한 그 순간에만 이름을 클라이언트에 줍니다. 그 뒤 재로그인에서는 givenName이 null이고, ID 토큰에도 이름이 없습니다.
- 값이 있으면 그 요청에
name으로 실어 보내세요. 놓치면 서버에 이름이 영영 안 남습니다 - 재로그인 때는
name없이 보내면 됩니다 — 서버가 기존 값을 유지합니다 - 테스트 중 이름을 다시 받고 싶으면 iOS 설정 > Apple 계정 > 로그인 및 보안 > Apple로 로그인에서 ditto를 지우고 다시 로그인하세요
토큰 재사용(재생 공격)을 막습니다. 서버는 rawNonce가 오면 sha256(rawNonce)를 토큰의 nonce 클레임과 대조하고, 안 오면 이 검증만 건너뜁니다. 보내는 쪽을 권장합니다.
const rawNonce = crypto.randomUUID(); // 원본은 우리가 보관
const hashed = await sha256Hex(rawNonce); // 애플에는 해시를 넘김
const result = await SignInWithApple.authorize({ nonce: hashed, scopes: 'name email' });
await api.post('/api/v1/users/social-login/apple/native', {
identityToken: result.response.identityToken,
rawNonce, // 서버에는 원본
name: joinName(result.response), // 최초 1회만 값이 있음
});사용자가 "이메일 가리기"를 고르면 @privaterelay.appleid.com 주소가 오고, 아예 안 올 수도 있습니다. 서버는 그대로 저장하며 로그인은 정상 진행됩니다. 이메일을 계정 식별이나 화면 표시에 쓰는 자리가 있으면 빈 값을 대비해 주세요.
카카오 일반 앱과 똑같이 온보딩에서 직접 받습니다. 애플로 로그인해도 signupRequired: true면 기존 회원가입 플로우(성별·나이 필수)를 그대로 태우면 됩니다 → Frontend-Kakao-General-App-Guide
같은 사람이 카카오로 가입한 뒤 애플로 로그인하면 별도 회원이 됩니다(이메일이 같아도). 애플 릴레이 주소는 신뢰할 수 없고, 이메일 일치를 계정 병합 근거로 삼는 건 계정 탈취 경로라 잇지 않기로 했습니다.
화면에서 이걸 어떻게 안내할지 정해야 합니다. 로그인 화면에서 "이전에 카카오로 시작하셨다면 카카오로 로그인해 주세요" 정도의 문구를 권합니다. 계정 연결이 필요하다는 판단이면 별도 기능으로 논의해 주세요.
애플도 카카오와 동일합니다 — 탈퇴 후 30일 안에 같은 애플 계정으로 다시 로그인하면 계정이 복구됩니다.
| code | statusCode | 상황 | 앱 처리 |
|---|---|---|---|
1002 |
401 | ID 토큰 검증 실패 — 만료·서명 불일치·다른 앱에서 발급·nonce 불일치 | 애플 로그인을 다시 시도. 반복되면 로그인 화면 |
0001 |
400 |
identityToken 누락/빈 값, name 50자 초과 |
요청 점검 |
0003 |
403 |
X-API-Key 누락·오류 |
헤더 점검 |
9999 |
500 | 애플 공개키 서버 장애 등 | 잠시 후 재시도 안내 |
1002는 재시도로 풀리는 오류입니다(토큰 만료가 대부분). 사용자에게 "다시 시도해 주세요"로 안내하세요.
| 확인 | 내용 |
|---|---|
| ☐ | 웹: 로그인 화면에 애플 버튼 추가 → window.location.href = "/api/v1/users/social-login/APPLE"
|
| ☐ | 앱: 로그인 화면에 애플 버튼 추가 (심사 요건 — 애플 버튼 디자인 가이드 준수) |
| ☐ | 최초 인가에서 받은 이름을 name으로 전달 |
| ☐ |
rawNonce 전달 (권장) |
| ☐ |
signupRequired: true → 기존 온보딩(성별·나이 필수) 재사용 |
| ☐ | 이메일이 없거나 릴레이 주소인 경우의 화면 처리 |
| ☐ | 카카오/애플이 별도 계정임을 로그인 화면에서 안내 |
웹은 앱과 달리 기존 카카오 로그인과 똑같은 리다이렉트 방식입니다. FE가 할 일은 버튼 하나 추가하는 것뿐입니다.
// 카카오와 같은 패턴 — provider 만 다릅니다
window.location.href = "/api/v1/users/social-login/APPLE";그 다음은 서버와 애플이 처리하고, 최종적으로 지금 쓰는 그 콜백 페이지로 돌아옵니다:
/auth/callback?accessToken=...&signupRequired=... (정상)
/auth/callback?sanctioned=true&sanctionCode=... (제재)
refreshToken도 카카오와 동일하게 HttpOnly 쿠키로 내려갑니다. /auth/callback 처리 코드를 고칠 필요가 없습니다.
- 중간에 애플이 우리 서버로 POST 콜백을 보냅니다(
response_mode=form_post). 이건 브라우저↔애플↔서버 사이의 일이라 FE가 볼 일은 없습니다 — 다만 네트워크 탭에 POST가 찍히는 게 정상입니다 - 웹은 앱과 다른 식별자(Services ID) 를 쓰지만 같은 애플 계정이므로, 같은 회원으로 이어집니다 (앱에서 가입 → 웹에서 애플 로그인 OK)
- 이름은 여기서도 최초 인가 1회만 옵니다. 서버가
user폼 필드에서 읽어 저장하므로 FE가 할 일은 없습니다 - 애플 로그인 버튼 디자인은 웹에서도 애플 가이드라인을 따라야 합니다
애플 개발자 콘솔에 Services ID와 Return URL 등록이 필요합니다. 등록 전에는 애플이 인가 요청을 거부하므로, FE에서 버튼을 켜기 전에 백엔드에 준비 완료 여부를 확인해 주세요.
- 전체 스펙(Swagger UI): https://api.ditto.pics/docs — 태그
OAuth - 이슈/PR: #163 · PR #164(앱) / #165 · PR #166(웹)
- 설계 배경(레포):
docs/adr/0022-apple-native-login-id-token.md(앱) ·docs/adr/0023-apple-web-login-form-post-callback.md(웹) ·docs/domains/auth.md - 애플 문서: Verifying a user
- 관련 가이드: Frontend-Native-Login-Peer-Profile-Guide(카카오 네이티브 로그인) · Frontend-Kakao-General-App-Guide(가입 필수값·신원 정보 보완)