Android Apple 로그인을 Firebase 웹 흐름(apple.com 제공자)으로 연결 · 설정 안내
This commit is contained in:
@@ -73,6 +73,20 @@ fvm flutter build apk --release --dart-define-from-file=config/kakao.env
|
|||||||
`https://<프로젝트 ID>.firebaseapp.com/__/auth/handler` 를 넣는다. 콘솔에서 켜지 않았으면 로그인이
|
`https://<프로젝트 ID>.firebaseapp.com/__/auth/handler` 를 넣는다. 콘솔에서 켜지 않았으면 로그인이
|
||||||
E-AUTH-11 로 끝난다.
|
E-AUTH-11 로 끝난다.
|
||||||
|
|
||||||
|
## Android Apple 로그인 — 앱에 넣을 값 없음
|
||||||
|
|
||||||
|
Android 는 Apple SDK 가 없어 Firebase 웹 흐름(`apple.com` 제공자 · `signInWithProvider`)으로 로그인한다.
|
||||||
|
값은 모두 콘솔에 둔다 — 빌드 옵션은 없다.
|
||||||
|
|
||||||
|
1. Apple 개발자 계정 「Identifiers → Services IDs」에 서비스 ID 를 만들고 「Sign in with Apple」을 켠다.
|
||||||
|
- Domains: `<프로젝트 ID>.firebaseapp.com`
|
||||||
|
- Return URLs: `https://<프로젝트 ID>.firebaseapp.com/__/auth/handler`
|
||||||
|
2. 「Keys」에서 Sign in with Apple 키를 만들고 .p8 를 받는다(키 ID · 팀 ID 기록). 키 파일은 저장소에 넣지 않는다.
|
||||||
|
3. Firebase 콘솔 Authentication → 로그인 방법 → Apple 에 서비스 ID · 팀 ID · 키 ID · 비공개 키를 넣는다.
|
||||||
|
4. 확인: Android 첫 화면 Apple → 브라우저 탭에서 Apple 로그인 → 앱 HOME.
|
||||||
|
|
||||||
|
iOS 는 지금처럼 Apple SDK(`AppleSignInProvider`)로 로그인한다.
|
||||||
|
|
||||||
## 서명
|
## 서명
|
||||||
|
|
||||||
`android/key.properties` 가 없으면 **릴리스 빌드가 의도적으로 실패**한다
|
`android/key.properties` 가 없으면 **릴리스 빌드가 의도적으로 실패**한다
|
||||||
|
|||||||
+1
-1
@@ -144,7 +144,7 @@ bool get isMockSessionAvailable => !FirebaseBoot.isLive && !_releaseMode;
|
|||||||
| 제공자 | 상태 | 구현 | 막고 있는 것 |
|
| 제공자 | 상태 | 구현 | 막고 있는 것 |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| Google | 실 코드 경로 | `GoogleSignInProvider` | **Firebase 콘솔에서 Google 제공자 미활성** + Android OAuth 클라이언트(SHA-1) 미등록 |
|
| Google | 실 코드 경로 | `GoogleSignInProvider` | **Firebase 콘솔에서 Google 제공자 미활성** + Android OAuth 클라이언트(SHA-1) 미등록 |
|
||||||
| Apple | 실 코드 경로 | `AppleSignInProvider` | Apple 개발자 키 + Xcode Capability + Android Service ID/redirect URI |
|
| Apple | 실 코드 경로 | iOS `AppleSignInProvider`(Apple SDK) · Android `OidcSignInProvider`(Firebase 웹 흐름 `apple.com`) | iOS Xcode Capability · Android 는 Firebase 콘솔 Apple 제공자에 서비스 ID · 키 등록(`BUILD.md` 「Android Apple 로그인」) |
|
||||||
| 카카오 | 실 코드 경로 | `KakaoSignInProvider` — 카카오 SDK 로그인 + 서버 `fnAuthKakao` 커스텀 토큰 | 카카오 네이티브 앱 키(`config/kakao.env`) · 서버 `KAKAO_APP_ID` |
|
| 카카오 | 실 코드 경로 | `KakaoSignInProvider` — 카카오 SDK 로그인 + 서버 `fnAuthKakao` 커스텀 토큰 | 카카오 네이티브 앱 키(`config/kakao.env`) · 서버 `KAKAO_APP_ID` |
|
||||||
| LINE | 실 코드 경로 | `OidcSignInProvider` — Firebase OIDC `oidc.line` | Firebase 콘솔 LINE 제공자 등록 |
|
| LINE | 실 코드 경로 | `OidcSignInProvider` — Firebase OIDC `oidc.line` | Firebase 콘솔 LINE 제공자 등록 |
|
||||||
|
|
||||||
|
|||||||
@@ -50,9 +50,16 @@ class AuthRepository extends ChangeNotifier {
|
|||||||
/// 돌려준다.
|
/// 돌려준다.
|
||||||
static List<SocialAuthProvider> _defaultProviders() => [
|
static List<SocialAuthProvider> _defaultProviders() => [
|
||||||
const GoogleSignInProvider(),
|
const GoogleSignInProvider(),
|
||||||
AppleSignInProvider(
|
// Android 는 Apple SDK 가 없어 Firebase 웹 흐름(`apple.com` 제공자)으로 간다 —
|
||||||
webAuthenticationOptions: appleWebAuthenticationOptionsFromEnvironment(),
|
// 서비스 ID · 키는 Firebase 콘솔 Apple 제공자 설정에 두고 앱에는 값이 없다.
|
||||||
),
|
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android)
|
||||||
|
const OidcSignInProvider(
|
||||||
|
AuthProviderKind.apple,
|
||||||
|
providerId: 'apple.com',
|
||||||
|
scopes: ['email', 'name'],
|
||||||
|
)
|
||||||
|
else
|
||||||
|
const AppleSignInProvider(),
|
||||||
// 동의 항목은 카카오 콘솔 설정을 따른다(지금은 닉네임). 이메일(account_email)은 비즈 앱
|
// 동의 항목은 카카오 콘솔 설정을 따른다(지금은 닉네임). 이메일(account_email)은 비즈 앱
|
||||||
// 전환 후 콘솔에서 켜면 서버가 동의·인증된 값만 받는다.
|
// 전환 후 콘솔에서 켜면 서버가 동의·인증된 값만 받는다.
|
||||||
KakaoSignInProvider(),
|
KakaoSignInProvider(),
|
||||||
|
|||||||
@@ -482,25 +482,6 @@ Future<T> untilAbandoned<T>(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apple Service ID와 callback URL은 비밀값이 아니지만 환경별 값이다.
|
|
||||||
/// 저장소에 임시 상수를 박지 않고 빌드 시 `--dart-define`으로만 받는다.
|
|
||||||
apple.WebAuthenticationOptions? appleWebAuthenticationOptionsFromEnvironment() {
|
|
||||||
const clientId = String.fromEnvironment('FANUZU_APPLE_SERVICE_ID');
|
|
||||||
const redirect = String.fromEnvironment('FANUZU_APPLE_REDIRECT_URI');
|
|
||||||
if (clientId.isEmpty || redirect.isEmpty) return null;
|
|
||||||
|
|
||||||
final redirectUri = Uri.tryParse(redirect);
|
|
||||||
if (redirectUri == null ||
|
|
||||||
!redirectUri.hasScheme ||
|
|
||||||
!redirectUri.hasAuthority) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return apple.WebAuthenticationOptions(
|
|
||||||
clientId: clientId,
|
|
||||||
redirectUri: redirectUri,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthAccount _toAccount(fb.User? user, SocialProvider provider) => AuthAccount(
|
AuthAccount _toAccount(fb.User? user, SocialProvider provider) => AuthAccount(
|
||||||
uid: user?.uid ?? '',
|
uid: user?.uid ?? '',
|
||||||
provider: provider,
|
provider: provider,
|
||||||
|
|||||||
@@ -42,6 +42,24 @@ void main() {
|
|||||||
expect(providers[AuthProviderKind.kakao], isA<KakaoSignInProvider>());
|
expect(providers[AuthProviderKind.kakao], isA<KakaoSignInProvider>());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Apple: Android 는 Firebase 웹 흐름(apple.com) · iOS 는 Apple SDK', () {
|
||||||
|
final android = AuthRepository().providers.firstWhere(
|
||||||
|
(p) => p.provider == AuthProviderKind.apple,
|
||||||
|
);
|
||||||
|
expect(android, isA<OidcSignInProvider>());
|
||||||
|
expect(
|
||||||
|
(android as OidcSignInProvider).authProvider.providerId,
|
||||||
|
'apple.com',
|
||||||
|
);
|
||||||
|
expect(android.missingConfig, isEmpty);
|
||||||
|
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
|
||||||
|
addTearDown(() => debugDefaultTargetPlatformOverride = null);
|
||||||
|
final ios = AuthRepository().providers.firstWhere(
|
||||||
|
(p) => p.provider == AuthProviderKind.apple,
|
||||||
|
);
|
||||||
|
expect(ios, isA<AppleSignInProvider>());
|
||||||
|
});
|
||||||
|
|
||||||
test('Firebase 설정이 없으면 SDK 를 부르지 않고 미설정으로 닫는다', () async {
|
test('Firebase 설정이 없으면 SDK 를 부르지 않고 미설정으로 닫는다', () async {
|
||||||
FirebaseBoot.debugSetMode(FirebaseMode.mock, reason: '설정 없음');
|
FirebaseBoot.debugSetMode(FirebaseMode.mock, reason: '설정 없음');
|
||||||
final outcome = await line(_ThrowingAuth('should-not-call')).signIn();
|
final outcome = await line(_ThrowingAuth('should-not-call')).signIn();
|
||||||
|
|||||||
Reference in New Issue
Block a user