#php #firebase #flutter #firebase-authentication #jwt
#php #firebase #flutter #firebase-аутентификация #jwt
Вопрос:
Я использую аутентификацию Firebase в своем приложении Flutter для управления пользователями (Facebook, Google, электронная почта …). Когда пользователь входит в мое приложение, я отправляю токен Firebase на мой PHP-сервер, где этот токен проверяется с помощью JWT.
Проблема в том, что, хотя токен, сгенерированный при входе по электронной почте, правильно проверен, токен, сгенерированный при входе в Facebook или Google, завершается ошибкой с «SignatureInvalidException: проверка подписи не удалась».
Код входа в Facebook в приложении Flutter:
FirebaseAuth auth = FirebaseAuth.instance;
final LoginResult result = await FacebookAuth.instance.login();
final FacebookAuthCredential facebookAuthCredential = FacebookAuthProvider.credential(result.accessToken.token);
UserCredential user = await auth.signInWithCredential(facebookAuthCredential);
String token = await auth.currentUser.getIdToken();
print(token.toString());
Информация о токене правильно проверена в https://jwt.io / debugger, так что заголовок и полезная нагрузка в порядке.
На сервере PHP (один и тот же код для обоих случаев):
-
Проверка токена электронной почты и пароля (ОК):
Объект stdClass ( [iss] => https://securetoken .google.com/project-123546 [aud] => project-123546 [auth_time] => 1603424825 [user_id] => S2gpfdsa156dsacdsfQ2z1 [sub] => S2gpfdsa156dsacdsfQ2z1 [iat] => 1603424825 [exp] => 1603428425 [email] => user@example.com [email_verified] => [firebase] => Объект стандартного класса ([идентификаторы] => Объект стандартного класса ([email] => Массив ([0] => user@example.com ) ) [sign_in_provider] => пароль ) )
-
Проверка токена Facebook (KO):
Фатальная ошибка: неперехваченная Firebase JWT SignatureInvalidException: ошибка проверки подписи на сервере vendor firebase php-jwt src JWT.php: 122 Трассировка стека: # 0 servertoken.php (18): FirebaseJWTJWT::декодировать(‘eygswbdsasdJSUzI…’, ‘——BEGIN CERT …’, Массив) #1 {main}, добавленный servervendorfirebasephp-jwtsrcJWT.php в строке 122
PHP-код:
$token = "...TOKEN-FROM-APP...";
$pkeys_raw = file_get_contents('https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com');
$pkeys = json_decode($pkeys_raw, true);
$decoded = JWT::decode($token, $pkeys, ["RS256"]);
print_r($decoded);
Идентификатор ключа совпадает с ключом в https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com , но я думаю, что приложение (или Firebase) неправильно подписывает токен закрытым ключом при входе в Facebook и Google. Тем не менее, я тоже использую auth.currentUser.getIdToken()
адрес электронной почты и пароль для входа, поэтому различий нет.
Есть идеи, как это решить?
Ответ №1:
Исследуя библиотеку firebase для Flutter, я нашел ответ на эту проблему. Я публикую это здесь на всякий случай, если это кому-то помогло.
Библиотека в порядке, и подпись сгенерирована правильно. Причина совершенно не связана с библиотекой — DebugPrint() в Flutter / Dart на платформе Android не имеет достаточного буфера для распечатки всей строки токена. Итак, проблема в print(token.toString());
том, что если вы отправите токен на сервер, он будет правильно декодирован.
Вся информация об этой проблеме: https://github.com/FirebaseExtended/flutterfire/issues/2728
Ответ №2:
Я думаю, вы можете использовать log
для получения всего токена:
log(token);
Несмотря на то, что токен jwt каким-то образом недействителен https://jwt.io
, но я все еще могу проверить его с моего серверного сервера, который является Java, используя Firebase Admin SDK.
FirebaseAuth.getInstance(firebaseApp).verifyIdToken(token);
Ответ №3:
Кроме того, вы можете печатать следующим образом:
final idToken = await firebaseCredential.user!.getIdToken(true);
print(idToken.substring(0, 1000));
print(idToken.substring(1000));