Skip to content

🐛 [ui] Entering OTP on Android does not work AuthStateChangeAction SignedIn does not fire #7826

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
richard457 opened this issue Jan 9, 2022 · 29 comments
Assignees
Labels
plugin: ui resolution: fixed A fix has been merged or is pending merge from a PR. type: bug Something isn't working

Comments

@richard457
Copy link

richard457 commented Jan 9, 2022

Run the flutterfire/packages/flutterfire_ui/example app on the android simulator, try to log in using a phone number wait for the OTP and it does not come.
Capture

@richard457 richard457 added Needs Attention This issue needs maintainer attention. type: bug Something isn't working labels Jan 9, 2022
@pr-Mais
Copy link
Member

pr-Mais commented Jan 10, 2022

Did you add the phone number to testing as mentioned here? If so, you won't receive the OTP, instead you use the code listed for the testing numbers.
Additionally, is the Firebase Auth emulator running?

@darshankawar darshankawar added the triage Issue is currently being triaged. label Jan 10, 2022
@darshankawar
Copy link

@richard457
Check above and try by adding your phone number in Firebase console so that you can receive OTP on it.

@darshankawar darshankawar added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Jan 10, 2022
@richard457
Copy link
Author

richard457 commented Jan 10, 2022

@pr-Mais yes I did and as mentioned on the web AuthStateChangeAction is able to fire when state changes but on mobile (android) it does nothing. @darshankawar I added the testing number in firebase authentication. @pr-Mais emulator is running of cause! that's where I am testing my app.

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Jan 10, 2022
@richard457
Copy link
Author

Also would be nice to have errors shown on android.

@richard457 richard457 changed the title 🐛 Able to receive OTP in browser but not on simulator 🐛 Able to receive OTP in browser but not on emulator Jan 10, 2022
@pr-Mais
Copy link
Member

pr-Mais commented Jan 11, 2022

@richard457 so the number you're using for testing is added in the Firebase Console? in this case you will never receive any OTP, you use the OTP you setup with your test number on the console.

@richard457
Copy link
Author

richard457 commented Jan 11, 2022

yes I know, I use the otp I set from firebase, this is the behavior as mentioned on the web AuthStateChangeAction SignedIn is able to fire when state changes but on android after entering otp it does nothing @pr-Mais I mentioned this in the above comments too.

@pr-Mais
Copy link
Member

pr-Mais commented Jan 11, 2022

Could you please provide a reproducible sample code?

@richard457 richard457 changed the title 🐛 Able to receive OTP in browser but not on emulator 🐛 Entering OTP on Android does not work AuthStateChangeAction SignedIn does not fire Jan 11, 2022
@richard457
Copy link
Author

I am using the sample code you provided in flutterfire_ui and if you need a testing phone is +250 783 054 002 and OTP is 123456

@pr-Mais pr-Mais changed the title 🐛 Entering OTP on Android does not work AuthStateChangeAction SignedIn does not fire 🐛 [ui] Entering OTP on Android does not work AuthStateChangeAction SignedIn does not fire Jan 11, 2022
@pr-Mais
Copy link
Member

pr-Mais commented Jan 11, 2022

Using the example app, I can confirm that AuthStateChangeAction is being triggered on Android upon entering the SMS code. Uninstall the app on your emulator and try again.

ezgif com-gif-maker

@richard457
Copy link
Author

Recording 2022-01-11 at 09 49 33

@pr-Mais
Copy link
Member

pr-Mais commented Jan 11, 2022

Have you uninstalled the app and cleared cache?

@richard457
Copy link
Author

yes I did using adb uninstall

@pr-Mais
Copy link
Member

pr-Mais commented Jan 11, 2022

I see some logs saying you didn't set the signing certificate SHA-1, it's a required step for Phone authentication, make sure to follow the steps here to add it.

@richard457
Copy link
Author

you are right on your sample code did not add the sha1, but adding it does not solve the issue @pr-Mais

@richard457
Copy link
Author

richard457 commented Jan 11, 2022

you are right on your sample code did not add the SHA-1, but adding it does not solve the issue @pr-Mais I triple checked and in console, no other error showed this is what happened, after putting the OTP the browser opened for captcha and after confirming I am not a robot it closed, the SignedIn did not fire, attempt to click again the error State has already been listened to got fired!. again it could not be the issue of sha1 keys not being added on the firebase side since I tried an existing project that is configured with google phone auth and gave the same result.

@darshankawar
Copy link

@richard457
Can't see entirely from the video you shared, but make sure that your app's packagename/SHA256 pair is registered in the firebase console.
I guess the safety_net_token was passed, but there may not be any matching SHA-256.

@darshankawar darshankawar added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Jan 11, 2022
@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Jan 11, 2022
@richard457
Copy link
Author

Using the example app, I can confirm that AuthStateChangeAction is being triggered on Android upon entering the SMS code. Uninstall the app on your emulator and try again.

ezgif com-gif-maker

May I ask if possible to share the working example? I want to see the difference because I could not tell.

@pr-Mais
Copy link
Member

pr-Mais commented Jan 12, 2022

Are you using your own Firebase options or the ones that comes with the example app?

@richard457
Copy link
Author

Tried both, using my own and replacing them with my own.

@richard457
Copy link
Author

richard457 commented Jan 13, 2022

hello everyone, here is my finding, the widget is not easy to drop to an existing app somehow it assumes for example to use one sing page for auth, you can not have

PhoneInputScreen(
            actions: [
              SMSCodeRequestedAction((context, action, flowKey, phone) {
                Navigator.of(context).pushReplacementNamed(
                  '/sms',
                  arguments: {
                    'action': action,
                    'flowKey': flowKey,
                    'phone': phone,
                  },
                );
              }),
            ],
            headerBuilder: headerIcon(Icons.phone),
            sideBuilder: sideIcon(Icons.phone),
          )

on one screen and

SMSCodeInputScreen(
            actions: [
              AuthStateChangeAction<AuthFailed>((context, state) async {
                showSimpleNotification(
                  const Text('Auth failed'),
                  background: Colors.green,
                );
              }),
              AuthStateChangeAction<SignedIn>((context, state) async {
                await authAfter(state, arguments!);
              })
            ],
            flowKey: arguments?['flowKey'],
            action: arguments?['action'],
            headerBuilder: headerIcon(Icons.sms_outlined),
            sideBuilder: sideIcon(Icons.sms_outlined),
          )

on another screen this will throw errors, also if it is not put directly under MaterialApp it is going to throw an error too, even the top parent widget is a material... I think this is a limitation since you can not use it under for example a scaffold. then somehow I managed to get the OTP sent on the device could not tell what was different except a few things I tried that has nothing to do with the package, I believe there is something that is not well. overall the package is not in best state to be used as it is not predictable and would love to followup on this.

@richard457
Copy link
Author

richard457 commented Jan 13, 2022

hello everyone, here is my finding, the widget is not easy to drop to an existing app somehow it assumes for example to use one sing page for auth, you can not have

PhoneInputScreen(
            actions: [
              SMSCodeRequestedAction((context, action, flowKey, phone) {
                Navigator.of(context).pushReplacementNamed(
                  '/sms',
                  arguments: {
                    'action': action,
                    'flowKey': flowKey,
                    'phone': phone,
                  },
                );
              }),
            ],
            headerBuilder: headerIcon(Icons.phone),
            sideBuilder: sideIcon(Icons.phone),
          )

on one screen and

SMSCodeInputScreen(
            actions: [
              AuthStateChangeAction<AuthFailed>((context, state) async {
                showSimpleNotification(
                  const Text('Auth failed'),
                  background: Colors.green,
                );
              }),
              AuthStateChangeAction<SignedIn>((context, state) async {
                await authAfter(state, arguments!);
              })
            ],
            flowKey: arguments?['flowKey'],
            action: arguments?['action'],
            headerBuilder: headerIcon(Icons.sms_outlined),
            sideBuilder: sideIcon(Icons.sms_outlined),
          )

on another screen this will throw errors, also if it is not put directly under MaterialApp it is going to throw an error too, even the top parent widget is a material... I think this is a limitation since you can not use it under for example a scaffold. then somehow I managed to get the OTP sent on the device could not tell what was different except a few things I tried that has nothing to do with the package, I believe there is something that is not well. overall the package is not in the best state to be used as it is not predictable and would love to follow up on this.

The quick assumption is that it is okay to separate these screens and only go to the OTP verification screen once you got it, but NAH, it does not work, the only way you can somehow get the code to work is to use your sample code as it is, no other way around

@richard457
Copy link
Author

richard457 commented Jan 13, 2022

These sample can be useful, a sample that separates these screen MaterialApp->PhoneInPutScreen->SMSCodeInputScreen (NOTE that these screens are not in one widget) and also very important to wrap PhoneInPutScreen or SMSCodeInputScreen with whatever widget of choice, and if the root MaterialApp has some settings should be applied too for example theme from root widget should be applied. @pr-Mais @darshankawar

@richard457
Copy link
Author

for example this code will not work

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutterfire_ui/auth.dart';
import 'package:flutterfire_ui/i10n.dart';
import 'package:flutterfire_ui_example/phone.dart';

import 'init.dart'
    if (dart.library.html) 'web_init.dart'
    if (dart.library.io) 'io_init.dart';

import 'config.dart';
import 'decorations.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await initializeFirebase();
  runApp(FirebaseAuthUIExample());
}

// Overrides a label for en locale
// To add localization for a custom language follow the guide here:
// https://flutter.dev/docs/development/accessibility-and-localization/internationalization#an-alternative-class-for-the-apps-localized-resources
class LabelOverrides extends DefaultLocalizations {
  const LabelOverrides();

  @override
  String get emailInputLabel => 'Enter your email';
}

final emailLinkProviderConfig = EmailLinkProviderConfiguration(
  actionCodeSettings: ActionCodeSettings(
    url: 'https://reactnativefirebase.page.link',
    handleCodeInApp: true,
    androidMinimumVersion: '12',
    androidPackageName:
        'io.flutter.plugins.flutterfire_ui.flutterfire_ui_example',
    iOSBundleId: 'io.flutter.plugins.flutterfireui.flutterfireUIExample',
  ),
);

final providerConfigs = [
  const EmailProviderConfiguration(),
  emailLinkProviderConfig,
  const PhoneProviderConfiguration(),
  const GoogleProviderConfiguration(clientId: GOOGLE_CLIENT_ID),
  const AppleProviderConfiguration(),
  const FacebookProviderConfiguration(clientId: FACEBOOK_CLIENT_ID),
  const TwitterProviderConfiguration(
    apiKey: TWITTER_API_KEY,
    apiSecretKey: TWITTER_API_SECRET_KEY,
    redirectUri: TWITTER_REDIRECT_URI,
  ),
];

class FirebaseAuthUIExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final auth = FirebaseAuth.instance;

    return MaterialApp(
      theme: ThemeData(
        brightness: Brightness.light,
        visualDensity: VisualDensity.standard,
        inputDecorationTheme: const InputDecorationTheme(
          border: OutlineInputBorder(),
        ),
      ),
      initialRoute: '/',
      routes: {
        '/': (context) {
          return auth.currentUser == null
              ? const Phone()
              : ProfileScreen(providerConfigs: providerConfigs);
        },
        'sms': (context) {
          final arguments = ModalRoute.of(context)?.settings.arguments
              as Map<String, dynamic>?;
          return SMSCodeInputScreen(
            actions: [
              AuthStateChangeAction<SignedIn>((context, state) {
                Navigator.of(context).pushReplacementNamed('/profile');
              })
            ],
            flowKey: arguments?['flowKey'],
            action: arguments?['action'],
            headerBuilder: headerIcon(Icons.sms_outlined),
            sideBuilder: sideIcon(Icons.sms_outlined),
          );
        },
      },
    );
    
  }
}

@pr-Mais
Copy link
Member

pr-Mais commented Jan 13, 2022

cc @lesnitsky

@darshankawar darshankawar added plugin: ui and removed Needs Attention This issue needs maintainer attention. triage Issue is currently being triaged. labels Jan 13, 2022
@lesnitsky lesnitsky self-assigned this Jan 13, 2022
@richard457
Copy link
Author

@lesnitsky any update about this issue?

@richard457
Copy link
Author

richard457 commented Jan 21, 2022

StreamBuilder(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.hasData) {
          return const StartUpView();
        } else {
          return SignInScreen(
            headerBuilder: headerImage('assets/logo.png'),
            sideBuilder: sideImage('assets/logo.png'),
            subtitleBuilder: (context, action) {
              return Padding(
                padding: const EdgeInsets.only(bottom: 8),
                child: Text(
                  action == AuthAction.signIn
                      ? 'Welcome to app Please sign in to continue.'
                      : 'Welcome to app Please create an account to continue',
                ),
              );
            },
            footerBuilder: (context, action) {
              return Center(
                child: Padding(
                  padding: const EdgeInsets.only(top: 16),
                  child: Text(
                    action == AuthAction.signIn
                        ? 'By signing in, you agree to our terms and conditions.'
                        : 'By registering, you agree to our terms and conditions.',
                    style: const TextStyle(color: Colors.grey),
                  ),
                ),
              );
            },
            providerConfigs: [const PhoneProviderConfiguration()],
          );
        }
      },
    )

The above code throws this error when clicking on phone login.

 _CastError (Null check operator used on a null value)
[sentry.flutterError] #0      _PhoneInputViewState.build.<anonymous closure> i/…/views/phone_input_view.dart:95 

@lesnitsky

@richard457
Copy link
Author

{
screen: RecaptchaActivity, 
state: destroyed
}
FlutterError: Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

@richard457
Copy link
Author

@lesnitsky

@lesnitsky
Copy link
Member

lesnitsky commented Oct 21, 2022

fixed in #9343

@darshankawar darshankawar added the resolution: fixed A fix has been merged or is pending merge from a PR. label Oct 21, 2022
@firebase firebase locked and limited conversation to collaborators Nov 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
plugin: ui resolution: fixed A fix has been merged or is pending merge from a PR. type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants