Код: Выделить всё
flutter_facebook_authОшибка аутентификации Firebase: invalid-credential — {"code":190,"message":"Плохая подпись"
Среда
- Flutter 3.38.1
Код: Выделить всё
firebase_auth: ^6.1.4Код: Выделить всё
flutter_facebook_auth: ^7.1.2- Протестировано на симуляторе iOS (проблема также воспроизводится на физическом устройстве)
- Android отлично работает с тем же кодом Dart — никаких встроенных изменений не требуется
1 — Info.plist (схема URL-адресов и ключи Facebook)
Схема URL-адресов Facebook и необходимые ключи зарегистрированы:Код: Выделить всё
XML / Info.plist
CFBundleURLTypes
CFBundleURLSchemes
fb1234567890
FacebookAppID
1234567890
FacebookClientToken
your_client_token_here
FacebookDisplayName
MyApp
LSApplicationQueriesSchemes
fbapi
fb-messenger-share-api
2 — AppDelegate.swift (Futter по умолчанию, без кода Facebook)
Обработка обратного вызова, специфичная для Facebook, не была добавлена:Код: Выделить всё
Swiftimport Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// ⚠️ No open(_:options:) override — URL callbacks are NOT intercepted here
}
3 — код входа в Dart (стандартный токен доступа → поток Firebase)
Код: Выделить всё
Dart// Step 1 — trigger native Facebook login dialog
final LoginResult result = await FacebookAuth.instance.login(
permissions: ['email', 'public_profile'],
);
if (result.status != LoginStatus.success) {
// Handle cancelled / error
return;
}
// Step 2 — wrap the Facebook access token as a Firebase credential
final OAuthCredential credential =
FacebookAuthProvider.credential(result.accessToken!.tokenString);
// Step 3 — sign in to Firebase ← fails on iOS with error 190
await FirebaseAuth.instance.signInWithCredential(credential);
{"error":{"code":190,"message":"Bad Signature","type":"OAuthException"}
Что я пробовал — LoginTracking.limited с одноразовым номером
Я нашел потенциальную возможность альтернатива, которая полностью обходит перенаправление схемы URL-адресов и вместо этого использует поток idToken (ограниченный вход/вход через Facebook):
Код: Выделить всё
Dartimport 'dart:math';
import 'dart:convert';
import 'package:crypto/crypto.dart';
/// Generates a cryptographically random nonce string.
String generateNonce([int length = 32]) {
const charset =
'0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._';
final random = Random.secure();
return List.generate(length, (_) => charset[random.nextInt(charset.length)])
.join();
}
/// Returns the SHA-256 hex digest of [input].
String sha256ofString(String input) {
final bytes = utf8.encode(input);
final digest = sha256.convert(bytes);
return digest.toString();
}
// ── Auth flow ──────────────────────────────────────────────────────────
// 1. Generate a raw nonce and its SHA-256 hash
final rawNonce = generateNonce();
final nonce = sha256ofString(rawNonce);
// 2. Trigger Limited Login — returns an OIDC id_token instead of an access token
final LoginResult result = await FacebookAuth.instance.login(
loginTracking: LoginTracking.limited,
nonce: nonce, // hashed nonce bound to the id_token
);
if (result.status != LoginStatus.success) return;
// 3. Build an OAuthCredential using the id_token + raw nonce
final OAuthCredential credential = OAuthCredential(
providerId: 'facebook.com',
signInMethod: 'oauth',
idToken: result.accessToken!.tokenString, // OIDC id_token (not an access token)
rawNonce: rawNonce, // Firebase verifies nonce client-side
);
// 4. Sign in to Firebase — works on iOS ✅
await FirebaseAuth.instance.signInWithCredential(credential);
Похоже, это устраняет ошибку, но я хочу понять, почему, прежде чем переходить к этому.
Мои вопросы
- Требует ли iOS обновить AppDelegate.swift для обработки перенаправления схемы URL-адресов Facebook? Android работает без каких-либо эквивалентных собственных изменений — это потому, что Android обрабатывает перенаправление через фильтры намерений AndroidManifest.xml, тогда как в iOS приложение само должно перехватывать URL-адрес обратного вызова и пересылать его в Facebook SDK через application(_:open:options:)?
- Является ли LoginTracking.limited с nonce правильным/рекомендуемым исправлением для этого на iOS или обновляется? AppDelegate.swift — подходящее решение, а LoginTracking.limited — всего лишь обходной путь?
- Что именно вызывает ошибку 190 «Плохая подпись»? Это то, что перенаправление схемы URL никогда не завершается полностью на iOS без его обработки AppDelegate, из-за чего Facebook возвращает искаженный или неполный токен, который Firebase впоследствии не может проверить на приложении секрет?
Подробнее здесь: https://stackoverflow.com/questions/798 ... for-url-sc
Мобильная версия