Authentication — Native SDK Implementation
Status: Active Last updated: 2026-03-27 Supersedes: api-kakao.md (deprecated)
Architecture
All social login providers use their native SDKs to obtain an ID token, then exchange it with Supabase via signInWithIdToken. This is the correct approach per Supabase, Kakao, Google, and Apple documentation.
Login Screen → Native SDK login() → idToken → supabase.signInWithIdToken()
↓
Supabase Auth Server
- Validates JWT via JWKS
- Checks aud matches Client ID
- Creates/links user
- Returns session tokens
↓
DB trigger: handle_new_user()
- Auto-creates profiles row
- Pulls name from OAuth metadataNo browser-based OAuth. Native SDKs provide the official branded UI, handle biometrics/passkeys, and are required by App Store guidelines.
Providers
Kakao (Primary — Korean market)
Current SDK: @react-native-seoul/kakao-login in packages/app/src/adapters/supabase/auth.supabase.ts.
Target SDK: @react-native-kakao/core + @react-native-kakao/user after the auth rebuild slice. Do not treat the current @react-native-kakao/core share-plugin wiring in apps/mobile/app.config.js as proof that Kakao auth has migrated.
Flow:
- Native Kakao SDK login opens KakaoTalk or Kakao Account fallback.
- Current adapter calls the login bridge from
@react-native-seoul/kakao-login. - Returns
{ idToken, accessToken, ... }(idToken requires OIDC enabled) supabase.auth.signInWithIdToken({ provider: 'kakao', token: idToken })
Supabase Dashboard:
- Client ID: Kakao Native App Key.
- Client Secret: configure in Supabase/Kakao dashboard or environment only; do not commit secrets into docs.
Kakao Developers Console:
- OpenID Connect: ON
- Platform > Android: package
com.ivorybridge.twomore+ key hash fromgetKeyHashAndroid() - Platform > iOS: bundle
com.ivorybridge.twomore
Current gap: production Kakao auth credentials and native config proof remain external blockers. The @react-native-kakao/core plugin currently added through apps/mobile/app.config.js is for Kakao Share and is gated by TWOMORE_KAKAO_NATIVE_APP_KEY, with EXPO_PUBLIC_KAKAO_APP_KEY accepted as the backward-compatible fallback when it carries the same Kakao Native App Key.
Google
SDK: @react-native-google-signin/google-signin
Flow:
GoogleSignin.configure({ webClientId })at app startupGoogleSignin.signIn()→ native Google sign-in UI- Returns
{ data: { idToken } } supabase.auth.signInWithIdToken({ provider: 'google', token: idToken })
Supabase Dashboard:
- Client ID: Web Client ID
- Authorized Client IDs:
WEB_ID,IOS_ID,ANDROID_ID
Google Cloud Console:
- 3 OAuth Client IDs: Web, iOS (bundle), Android (package + SHA-1)
Apple (iOS only)
SDK: expo-apple-authentication
Flow:
AppleAuthentication.signInAsync({ requestedScopes: [FULL_NAME, EMAIL] })- Returns
{ identityToken, fullName } supabase.auth.signInWithIdToken({ provider: 'apple', token: identityToken })- Save
fullNameimmediately (Apple only sends on first sign-in)
Supabase Dashboard:
- Client ID: Bundle ID (
com.ivorybridge.twomore)
Android: Not available natively. Don't show button on Android.
Supabase Client ID Quick Reference
| Provider | Supabase "Client ID" | Why |
|---|---|---|
| Kakao | Native App Key | SDK sets aud to Native App Key |
| Web Client ID | Google sets aud to Web Client ID | |
| Apple | Bundle ID | Apple sets aud to bundle/service ID |
Hex Architecture
Domain: OAuthProvider ('kakao' | 'google' | 'apple')
Port: AuthServicePort.signInWithProvider(provider)
Adapter: Routes to native SDK → signInWithIdToken
Hook: useAuth().signInWithProvider(provider)
Screen: Branded provider buttons
Guard: AuthGuard → isAuthenticated + onboardingCompletedAtAdding a New Provider
- Add to
OAuthProviderinpackages/app/src/domain/entities/auth.entity.ts - Install native SDK
- Add initialization to
app/_layout.tsx - Add case to adapter's
signInWithProvider - Configure in Supabase Dashboard
- Add branded button to login screen
- Add i18n string
Key Files
| File | Purpose |
|---|---|
packages/app/src/domain/entities/auth.entity.ts | OAuthProvider type |
src/ports/services/auth.service.port.ts | Auth port |
packages/app/src/adapters/supabase/auth.supabase.ts | Native SDK routing |
packages/app/src/presentation/hooks/use-auth.ts | Auth hook |
packages/app/src/presentation/screens/auth/login-screen.tsx | Login UI |
apps/mobile/app.config.js | Kakao Share native plugin/env wiring; not Kakao auth proof |
supabase/migrations/00045_auto_create_profile.sql | Profile trigger |