flutterfire icon indicating copy to clipboard operation
flutterfire copied to clipboard

Firebase Auth: We need to upgrade package with new changes made in Facebook Login for iOS

Open RaghvindYadav opened this issue 1 year ago • 20 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues.

Which plugins are affected?

Auth

Which platforms are affected?

iOS

Description

I am integrating my app with Facebook login but facing a problem in iOS version which is greater than 17.0. The login get failed. Getting error : Firebase Auth error: [firebase_auth/invalid-credential] {"code":190,"message":"Invalid OAuth access token - Cannot parse access token"}

Reproducing the issue

Future<UserCredential> _signInWithFacebook(BuildContext context) async {
    // TODO - New code to check
    final FacebookLogin plugin = FacebookLogin(debug: false);

    await plugin.logIn(
        permissions: [
      FacebookPermission.publicProfile,
      FacebookPermission.email,
    ]);

    final accessToken = await plugin.accessToken;
    FacebookUserProfile? profile;

    if (accessToken != null) {
      profile = await plugin.getUserProfile();
      if (accessToken.permissions.contains(FacebookPermission.email.name)) {
        final email = await plugin.getUserEmail();
      }
      final imageUrl = await plugin.getProfileImageUrl(width: 100);
    }
    ////////////

    FacebookAuthProvider facebookProvider = FacebookAuthProvider();
    if (kIsWeb) {
      facebookProvider.addScope('email');
      facebookProvider.setCustomParameters({
        'display': 'popup',
      });

      return _firebaseAuth!.signInWithPopup(facebookProvider);
    }
    
    // Create a credential from the access token
    final OAuthCredential facebookAuthCredential =
        FacebookAuthProvider.credential(accessToken?.token ?? '');
    // Once signed in, return the UserCredential
    // return FirebaseAuth.instance.signInWithCustomToken(accessToken?.token??'');
    return FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
  }

The above is worked well for android and iOS device which ios version is less than 17, but we need to upgrade Facebook sign for iOS 17.o and greater. Here is a url of blog. https://developers.facebook.com/blog/post/2024/03/28/changes-made-to-fb-login-sdk/

Firebase Core version

2.30.1

Flutter Version

3.19.5

Relevant Log Output

flutter: [FB] Result: {error: null, status: Success, accessToken: {authenticationToken: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImVjMTFkNTAzNDFjMDhlODI4OTk2NTBlNmFmY2M2NjY4ZjJhMGE0MjAifQ.eyJpc3MiOiJodHRwczpcL1wvd3d3LmZhY2Vib29rLmNvbSIsImF1ZCI6IjE1NTUyNTg3NTg2NTUzMzIiLCJzdWIiOiIxMjIxMzkwNjc4ODYxNzU1OTkiLCJpYXQiOjE3MTQxNzYyODksImV4cCI6MTcxNDE3OTg4OSwianRpIjoiSlZhcS42Zjc0N2I2OGI1MjkyYzQyOWFhOGUxMzJlY2NmNjk3YjVmMTc0M2Y0ZGRlMTMwNmE5MmRmODUzZjA1NTNlYjZjIiwibm9uY2UiOiJFQjlFQ0IwMi00ODFELTQyQTItOUE1MC1FOEI0RUQ3M0NGODUiLCJhdF9oYXNoIjoiajRKSzB3S2FDSHRldGd4aGRGd2gtZyIsImVtYWlsIjoiamFoYW52aVx1MDA0MGJhcmFnYXVuLmNvbSIsImdpdmVuX25hbWUiOiJKYWhhbnZpIiwiZmFtaWx5X25hbWUiOiJWeWFzIiwibmFtZSI6IkphaGFudmkgVnlhcyIsInBpY3R1cmUiOiJodHRwczpcL1wvc2NvbnRlbnQuZmRlbDgtMi5mbmEuZmJjZG4ubmV0XC92XC90MS4zMDQ5Ny0xXC84NDYyODI3M18xNzYxNTk4MzAyNzc4NTZfOTcyNjkzMzYzOTIyODI5MzEyX24uanBnP3N0cD1jMjkuMC4xMDAuMTAwYV9jcDBfZHN0LWpwZ19lMTVfcDEwMHgxMDBfcTY1Jl9uY19jYXQ9MSZjY2I9MS03Jl9uY19zaWQ9NWYyMDQ4JmVmZz1leUpwSWpvaWRDSjkmX25jX29oYz1CVlM2QW<…>
flutter: [FB] User profile: {lastName: Vyas, middleName: Jahanvi, userId: 122139067886175599, name: Jahanvi Vyas, firstName: Jahanvi}
flutter: [FB] User email: [email protected]
flutter: [FB] Profile image url: https://scontent.fdel8-2.fna.fbcdn.net/v/t1.30497-1/84628273_176159830277856_972693363922829312_n.jpg?stp=c29.0.100.100a_cp0_dst-jpg_e15_p100x100_q65&_nc_cat=1&ccb=1-7&_nc_sid=5f2048&efg=eyJpIjoidCJ9&_nc_ohc=BVS6Ae2-uyAQ7kNvgHEo4RD&_nc_oc=AdhEHeY3YZ9W-SomsGZUHYPhA5UxCD2iN296IXccqohR-pI0LCp3rB95NvhQrXFkkB8&_nc_ht=scontent.fdel8-2.fna&oh=00_AfBVJ1TElKJMGoMenXc_CKJRACuWfhY00dXvycsxQy8TMA&oe=6653A6D9
flutter: App inactive
flutter: App resumed
flutter: Firebase Auth error: [firebase_auth/invalid-credential] {"code":190,"message":"Invalid OAuth access token - Cannot parse access token"}

Flutter dependencies

name: mm_flutter_app
description: A new Flutter project.
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: "none" # Remove this line if you wish to publish to pub.dev

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1

environment:
  sdk: ">=3.2.3 <4.0.0"
  flutter: 3.19.5

# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
  flutter:
    sdk: flutter

  badges: ^3.1.1
  collection: ^1.17.1
  crop_image: ^1.0.12
  cross_file: ^0.3.3+8
  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  desktop_drop: ^0.4.4
  device_info_plus: ^9.1.2
  devicelocale: ^0.7.0
  dio: ^5.0.1
  dots_indicator: ^3.0.0
  dotted_border: ^2.1.0
  email_validator: ^2.1.17
  expandable: ^5.0.1
  file_picker: ^8.0.0+1
  firebase_auth: ^4.19.4
  firebase_core: ^2.30.1
  firebase_crashlytics: ^3.5.4
  firebase_messaging: ^14.9.1
  flutter_dotenv: ^5.0.2
  flutter_image_compress: 2.0.4
  flutter_linkify: ^6.0.0
  flutter_localizations:
    sdk: flutter
  flutter_markdown: ^0.6.18
  flutter_native_timezone: ^2.0.0
  flutter_rating_bar: ^4.0.1
  flutter_swipe_action_cell: ^3.1.2
  flutter_typeahead: ^5.2.0
  font_awesome_flutter: ^10.3.0
  go_router: ^13.2.1
  google_fonts: ^6.1.0
  google_sign_in: ^6.2.1
  gql: ^1.0.0
  gql_transform_link: ^1.0.0
  graphql_codegen: ^0.13.5
  graphql_flutter: ^5.1.2
  grouped_list: ^5.1.2
  http: ^1.1.0
  image: ^4.1.7
  intl: any
  local_auth: ^2.1.6
  logger: ^2.0.2+1
  mocktail: ^1.0.1
  package_info_plus: ^4.2.0
  path: ^1.8.3
  path_provider: ^2.1.2
  phone_numbers_parser: ^8.1.0
  provider: ^6.0.5
  retry: ^3.1.2
  shared_preferences: ^2.0.17
  textfield_tags: ^3.0.1
  tuple: ^2.0.2
  url_launcher: ^6.1.12
  uuid: ^4.3.3
  image_picker: ^1.0.8
  permission_handler: ^11.3.1
#  flutter_facebook_auth: ^6.2.0
  carousel_slider: ^4.2.1
  cached_network_image: ^3.3.1
  flutter_login_facebook: ^2.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  # TODO: commenting integration test as some of dependencies are not compatible
  # integration_test:
  #   sdk: flutter

  # The "flutter_lints" package below contains a set of recommended lints to
  # encourage good coding practices. The lint set provided by the package is
  # activated in the `analysis_options.yaml` file located at the root of your
  # package. See that file for information about deactivating specific lint
  # rules and activating additional ones.
  flutter_lints: ^3.0.1
  analyzer: 6.2.0

  # widgetbook: ^2.4.1
  # widgetbook_annotation: ^2.1.0
  # widgetbook_generator: ^2.4.1
  build_runner: ^2.3.3
  flutter_launcher_icons: ^0.13.0

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# https://pub.dev/packages/flutter_launcher_icons
flutter_icons:
  android: "launcher_icon"
  ios: true
  image_path: "assets/icon/icon.png"
  min_sdk_android: 21 # android min sdk min:16, default 21
  web:
    generate: true
    image_path: "assets/icon/iconcircle.png"
    background_color: "#hexcode"
    theme_color: "#hexcode"
  windows:
    generate: true
    image_path: "assets/icon/iconcircle.png"
    icon_size: 48 # min:48, max:256, default: 48
  macos:
    generate: true
    image_path: "assets/icon/iconcircle.png"
# The following section is specific to Flutter packages.
flutter:
  # Ensures that the translated files are generated
  generate: true
  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  assets:
    - assets/images/
    - assets/icon/
  # assets:
  #   - images/a_dot_burr.jpeg
  #   - images/a_dot_ham.jpeg

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages

Additional context and comments

https://developers.facebook.com/blog/post/2024/03/28/changes-made-to-fb-login-sdk/

RaghvindYadav avatar Apr 27 '24 04:04 RaghvindYadav

same issue in my unity game. Unity: 2021.3.37f1 Firebase SDK: 10.2.0 Facebook SDK: 17.0.0

Error Message: SignInWithCredentialAsync encountered an error: System.AggregateException: One or more errors occurred. (One or more errors occurred. (Bad access token: {"code":190,"message":"Malformed access token"}))

Firebase.FirebaseException: Bad access token: {"code":190,"message":"Invalid OAuth access token - Cannot parse access token"}

owllyi avatar Apr 28 '24 06:04 owllyi

@owllyi Have you find any solution?

RaghvindYadav avatar Apr 29 '24 04:04 RaghvindYadav

Hello @RaghvindYadav,

Thank you for reporting this issue. Based on the link you shared, it appears that the problem may not be related to FlutterFire but rather to the Facebook SDK plugin you are using. Did I understand that correctly? If so, you might consider opening an issue in their respective repository to get further assistance.

TarekkMA avatar Apr 29 '24 08:04 TarekkMA

Hi @TarekkMA May be you are right but I am getting failed error at this line of code return FirebaseAuth.instance.signInWithCredential(facebookAuthCredential); And FirbaseAuth comes form firebase_auth package.

RaghvindYadav avatar Apr 29 '24 08:04 RaghvindYadav

I will attempt to reproduce this issue. In the meantime, you might find it helpful to look at a similar issue reported with the Facebook SDK here: facebook-ios-sdk issue #2365. This may provide some insights into the problem you are encountering. Additionally, I suspect that FlutterFire may not be responsible for this error, but I will confirm this as I investigate further.

TarekkMA avatar Apr 29 '24 10:04 TarekkMA

Hi @RaghvindYadav,

The issue is due to the Facebook SDK/plugin. As mentioned here we need to get the nonce. We'll need a plugin that supports limited login to utilize this updated code snippet:

final provider = OAuthCredential(
  providerId: 'facebook.com',
  signInMethod: 'oauth',
  idToken: accessToken.token,
  rawNonce: rawNonce,
);

TarekkMA avatar Apr 29 '24 12:04 TarekkMA

@TarekkMA I did the above you mentioned, still getting the same error. Also use a new package https://pub.dev/packages/flutter_facebook_auth/versions/7.0.0-dev.3/changelog#700-dev3

RaghvindYadav avatar Apr 29 '24 15:04 RaghvindYadav

@owllyi Have you find any solution?

#if UNITY_ANDROID credential = Firebase.Auth.FacebookAuthProvider.GetCredential(accessToken); #elif UNITY_IOS var authToken = FaceBookManager.Instance.GetToken(); var nonce = FaceBookManager.Instance.GetNonce(); credential = Firebase.Auth.OAuthProvider.GetCredential("facebook.com", authToken, nonce, null); #endif

owllyi avatar Apr 30 '24 02:04 owllyi

@TarekkMA I did the above you mentioned, still getting the same error. Also use a new package https://pub.dev/packages/flutter_facebook_auth/versions/7.0.0-dev.3/changelog#700-dev3

Thank you @TarekkMA, I used that package but still persisting with same problem. Now accessToken looks quite different than previous response.

RaghvindYadav avatar Apr 30 '24 05:04 RaghvindYadav

I've looked into the new package, can you try using this instead and let me know if it works:

      final AccessToken accessToken = result.accessToken!;

      final AuthCredential credential;

      switch (accessToken.type) {
        case AccessTokenType.classic:
          final token = accessToken as ClassicToken;
          credential = FacebookAuthProvider.credential(token.authenticationToken!,);
          break;
        case AccessTokenType.limited:
          final token = accessToken as LimitedToken;
          credential = OAuthCredential(
            providerId: 'facebook.com',
            signInMethod: 'oauth',
            idToken: token.tokenString,
            rawNonce: token.nonce,
          );
          break;
      }

      // Login with token
      await auth.signInWithCredential(credential);

We might need to add a new option in the future for limited login so it can be just FacebookAuthProvider.limitedCredential(....)

TarekkMA avatar Apr 30 '24 05:04 TarekkMA

@TarekkMA AccessTokenType.limited getting this error for now Firebase Auth error: [firebase_auth/missing-or-invalid-nonce] The nonce in ID Token "C7D21692-B861-4E45-A912-DB9F4502AA2B" does not match the SHA256 hash of the raw nonce "C7D21692-B861-4E45-A912-DB9F4502AA2B" in the request.

If I changed this parameter signInMethod: 'oauth' to signInMethod: 'facebook.com', then app get crashed.

RaghvindYadav avatar Apr 30 '24 06:04 RaghvindYadav

I can reproduce this error, I guess the signInMethod should be oauth for it to work, since signInMethod: 'facebook.com' will not use nonce, or the idToken.

/cc @Lyokone

TarekkMA avatar Apr 30 '24 07:04 TarekkMA

@owllyi does your implementation work?

var authToken = FaceBookManager.Instance.GetToken(); var nonce = FaceBookManager.Instance.GetNonce(); credential = Firebase.Auth.OAuthProvider.GetCredential("facebook.com", authToken, nonce, null);

Would be interesting how your facebook-login implementation looks like. I got this error: The nonce in ID Token "xxx" does not match the SHA256 hash of the raw nonce "xxx" in the request

Do you use the hashed nonce or raw nonce in FB.Mobile.LoginWithTrackingPreference method?

onMouseUp avatar May 05 '24 09:05 onMouseUp

@owllyi does your implementation work?

var authToken = FaceBookManager.Instance.GetToken(); var nonce = FaceBookManager.Instance.GetNonce(); credential = Firebase.Auth.OAuthProvider.GetCredential("facebook.com", authToken, nonce, null);

Would be interesting how your facebook-login implementation looks like. I got this error: The nonce in ID Token "xxx" does not match the SHA256 hash of the raw nonce "xxx" in the request

Do you use the hashed nonce or raw nonce in FB.Mobile.LoginWithTrackingPreference method?

Found a solution. This is what I found in firebase documentation:

"You will send the SHA-256 hash of the nonce with your sign-in request, which Facebook will pass unchanged in the response. Firebase validates the response by hashing the original nonce and comparing it to the value passed by Facebook."

Facebook-Login: string rawNonce = Nonce.GetNonce() // custom class that will create a nonce string hashedNonce = HashUtils.Sha256(rawNonce); // custom class that will hash the rawNonce FB.Mobile.LoginWithTrackingPreference(LoginTracking.LIMITED, scopes, hashedNonce, HandleResult);

Firebase Credentials: Credentials credential = Firebase.Auth.OAuthProvider.GetCredential("facebook.com", authToken, rawNonce, null); // authToken - the token you will get from facebook response // rawNonce - nonce you created in the previous step

onMouseUp avatar May 06 '24 20:05 onMouseUp

I'm having this issue too with Flutter on IOS. The same code worked less than two months aga. The problem only occurs for me on IOS, not on Android.

hombrevago avatar May 11 '24 11:05 hombrevago

after reading this thread I tried it on iphone 14 running iOS 16.4 in IOS Emulator. It works there. In iOS 17.4 it fails.

hombrevago avatar May 11 '24 15:05 hombrevago

Workaround (downgrade facebook sdk version): 1) in pubspec.yaml replace flutter_facebook_auth: ^6.0.3 to flutter_facebook_auth: 6.0.3 2) flutter clean (not necessary, in my case worked without it) 3) Delete folders: /ios/Pods/FBAEMKit /ios/Pods/FBSDKCoreKit /ios/Pods/FBSDKCoreKit_Basics /ios/Pods/FBSDKLoginKit (also can delete all folder /ios/Pods) 4) Delete /ios/Podfile.lock 5) flutter pub get 6) from inside ios folder: pod install

After this my old code works on physical device iPhone 11 iOS 17.4.1

usilitel avatar May 15 '24 07:05 usilitel

Firebase Auth iOS has documentation on how to login with limited login here: https://firebase.google.com/docs/auth/ios/facebook-login#implement_facebook_limited_login

The difference is, they create a nonce, and send a SHA-256 hash of the nonce to FacebookAuth, whilst passing in the raw nonce to firebase_auth OAuthCredential which you use to signInWithCredential():

OAuthCredential credential = OAuthCredential(
    providerId: 'facebook.com',
    signInMethod: 'oauth',
    idToken: token.tokenString,
    rawNonce: rawNonce,
  );

The above will work for limited login if you set it up correctly.

russellwheatley avatar May 15 '24 11:05 russellwheatley

Any update on this? I have the same issue.

rgillera avatar May 16 '24 09:05 rgillera

Workaround (downgrade facebook sdk version): 1) in pubspec.yaml replace flutter_facebook_auth: ^6.0.3 to flutter_facebook_auth: 6.0.3 2) flutter clean (not necessary, in my case worked without it) 3) Delete folders: /ios/Pods/FBAEMKit /ios/Pods/FBSDKCoreKit /ios/Pods/FBSDKCoreKit_Basics /ios/Pods/FBSDKLoginKit (also can delete all folder /ios/Pods) 4) Delete /ios/Podfile.lock 5) flutter pub get 6) from inside ios folder: pod install

After this my old code works on physical device iPhone 11 iOS 17.4.1

I found the workaround provided by @usilitel to work on IOS emulators and physical devices up to IOS 17.4.1. I haven't tried the method presented by @russellwheatley thus far, but if there are any thoughts as to "why?" downgrading works and the current version doesn't, and how if at all it relates to the issue described by @russellwheatley that would be of tremendous assistance. Thank you both though.

hombrevago avatar May 16 '24 12:05 hombrevago

This worked for me using flutter_facebook_auth: ^7.0.0

String sha256ofString(String input) {
  final bytes = utf8.encode(input);
  final digest = sha256.convert(bytes);
  return digest.toString();
}

String generateNonce([int length = 32]) {
  final charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-.';
  final random = Random.secure();
  return List.generate(length, () => charset[random.nextInt(charset.length)]).join();
}

Future signInWithFacebook() async {
// Trigger the sign-in flow
  final rawNonce = generateNonce();
  final nonce = sha256ofString(rawNonce);
  final result = await FacebookAuth.instance.login(
    loginTracking: LoginTracking.limited,
    nonce: nonce,
  );
  if (result.status == LoginStatus.success) {
    print('${await FacebookAuth.instance.getUserData()}');
    final token = result.accessToken as LimitedToken;
// Create a credential from the access token
    OAuthCredential credential = OAuthCredential(
      providerId: 'facebook.com',
      signInMethod: 'oauth',
      idToken: token.tokenString,
      rawNonce: rawNonce,
    );
    await FirebaseAuth.instance.signInWithCredential(credential);
  }
}

darkodub avatar May 20 '24 09:05 darkodub

Hey @RaghvindYadav. We need more information to resolve this issue but there hasn't been an update in 7 weekdays. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

google-oss-bot avatar May 29 '24 01:05 google-oss-bot

Since there haven't been any recent updates here, I am going to close this issue.

@RaghvindYadav if you're still experiencing this problem and want to continue the discussion just leave a comment here and we are happy to re-open this.

google-oss-bot avatar Jun 07 '24 01:06 google-oss-bot