Skip to content

POST /api/v1/auth/apple/token

의도

Apple Identity Token(RS256 JWT)으로 dartbrief JWT를 발급한다. 첫 로그인이면 자동으로 계정 생성.

인증

없음 (로그인 전 호출)

입력

json
{
  "identity_token": "<Apple Identity Token>",
  "raw_nonce": "<랜덤 문자열 원본>"
}

두 필드 모두 필수. 하나라도 빈 문자열이면 400 반환.

응답

200 OK

json
{ "token": "eyJhbGci..." }

400 Bad Request — identity_token 또는 raw_nonce 누락

401 Unauthorized — Apple 토큰 검증 실패

curl 예제

bash
curl -s -X POST https://api.dartbrief.com/api/v1/auth/apple/token \
  -H "Content-Type: application/json" \
  -d '{"identity_token":"<Apple ID Token>","raw_nonce":"<rawNonce>"}' | jq

# 로컬
curl -s -X POST http://localhost:8000/api/v1/auth/apple/token \
  -H "Content-Type: application/json" \
  -d '{"identity_token":"<Apple ID Token>","raw_nonce":"<rawNonce>"}' | jq

Nonce 플로우

Replay 공격 방지를 위해 nonce를 필수로 사용한다.

Flutter 앱:
  1. rawNonce = 32자 무작위 문자열 (Random.secure())
  2. hashedNonce = sha256(rawNonce)
  3. SignInWithApple.getAppleIDCredential(nonce: hashedNonce)
     → Apple이 identity_token의 nonce claim에 hashedNonce를 삽입
  4. POST { identity_token, raw_nonce: rawNonce }

백엔드:
  5. sha256(rawNonce) == token.nonce claim 일치 여부 검증
  6. 불일치 시 401 반환

비즈니스 메모

  • Apple Identity Token 유효기간 약 10분 — nonce 없으면 이 시간 안에 replay 가능
  • 백엔드가 Apple JWKS (https://appleid.apple.com/auth/keys, 6h 캐시)로 RS256 서명 검증
  • aud claim이 APPLE_ALLOWED_CLIENT_IDS 목록 중 하나와 일치해야 함
    • dev: com.dartbrief.app.dev
    • prod: com.dartbrief.app
  • oauth_provider = 'APPLE', oauth_id = sub claim 으로 users 테이블 upsert
  • iOS 전용 — Android에서는 Apple 로그인 버튼 미노출 (defaultTargetPlatform == TargetPlatform.iOS)
  • Apple은 최초 로그인 시에만 email/fullName 반환 — 서버에 저장하지 않음 (oauth_id만 사용)