Firebase Email Passwordless Authentication Wont work

273 views Asked by At

I'm at my wits end with this overly complicated process of getting deep links working just to attempt to authenticate my users with a passwordless login.

I have wasted 3 days now googling and watching(very few actually) youtube videos that deal with this feature and reading forums and github issues trying to get the email passwordless functionality working. The documentation is vague at best and seems outdated as they are updating and refactoring constantly.

Between these guides...

https://firebase.google.com/docs/dynamic-links/flutter/create,

https://firebase.google.com/docs/auth/flutter/email-link-auth,

https://www.youtube.com/watch?v=JHTSgFl8VH0

plus a bunch of outdated tutorials just to see if I can find any similarities and nothing works,

I tried to setup it up with my own domain and went through the steps of adding DNS records to my webhosting site, Ive added in the JSON file into my .well-known folder on my domain.

I've added my domain and the default given domain that firebase gave me to the authorizedDomainLists.

Ive updated my androidManifest as per many instructions:

    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <!-- If a user clicks on a shared link that uses "http" scheme, 
            the app should be able to delegate that traffic to "https". -->
        <data android:scheme="http" />
        <data android:scheme="https" />

        <!-- Include one or more domains that should be verified. -->
        <data android:host="example.page.link" />
    </intent-filter>

I've added in the sdks needed for dynamiclinks

The firebase example on their pub.dev firebase_dynamicLinks doesnt seem to work either as they call navigator in the Main() method but theres no context like this...

  final PendingDynamicLinkData? initialLink = await FirebaseDynamicLinks.instance.getInitialLink();

  if (initialLink != null) {
    final Uri deepLink = initialLink.link;
    // Example of using the dynamic link to push user toa different screen
    //Navigator.pushNamed(context, deepLink.path);
  }

  FirebaseDynamicLinks.instance.onLink.listen(
    (pendingDynamicLinkData) {
      // Set up the `onLink` event listener next as it may be received here

      final Uri deepLink = pendingDynamicLinkData.link;
      // Example of using the dynamic link to push the user to a different screen
      //Navigator.pushNamed(context, deepLink.path);
    },
  );

I have a sendEmailLink method here:

  Future<AppResponse> sendEmailLink({required String email}) async {
    final actionCodeSettings = ActionCodeSettings(
      url: deepLinkPrefix,
      handleCodeInApp: true,
      androidPackageName: packageName,
      iOSBundleId: packageName,
    );
    await auth.sendSignInLinkToEmail(
      email: email,
      actionCodeSettings: actionCodeSettings,
    );
    return AppResponse.success(
      id: 'sendSignInLinkToEmail',
      message: 'Email link sent successfully',
    );
  }

AppResponse is just a alert dialog that the guy in the youtube video used.

And the retrievelink method that I can never get to so I can even see if THAT part works or not.

  // fromColdState means if the app was closed
  Future<AppResponse> retrieveDynamicLinkAndSignIn({required bool fromColdState}) async {
    try {
      PendingDynamicLinkData? dynamicLinkData;

      // Decide where to get link from if App is closed or not
      if (fromColdState) {
        dynamicLinkData = await FirebaseDynamicLinks.instance.getInitialLink();
      } else {
        dynamicLinkData = await FirebaseDynamicLinks.instance.onLink.first;
      }
      if (dynamicLinkData == null) {
        return AppResponse.notFound(
          id: 'retrieveDynamicLinkAndSignIn',
          message: 'No Credentials Found',
        );
      }

      // Check if link is valid
      bool validLink = auth.isSignInWithEmailLink(dynamicLinkData.link.toString());
      if (validLink) {
        // Get the users email address from the continueUrl
        final continueUrl = dynamicLinkData.link.queryParameters['continueUrl'] ?? '';
        final email = Uri.parse(continueUrl).queryParameters['email'] ?? '';

        // Use email to sign in with credentials
        final UserCredential userCredential = await auth.signInWithEmailLink(
          email: email,
          emailLink: dynamicLinkData.link.toString(),
        );

        // Check to make sure user credential is not null
        if (userCredential.user != null) {
          return AppResponse.success(
            id: 'signInWithEmailLink',
            message: 'Signed in successfully',
          );
        } else {
          return AppResponse.notFound(
            id: 'signInWithEmailLink',
            message: 'Not able to sign in',
          );
        }
      } else {
        return AppResponse.notFound(
          id: 'signInWithEmailLink',
          message: 'Link is not valid',
        );
      }
    } catch (e, s) {
      return AppResponse.error(
        id: 'signInWithEmailLink',
        error: e,
        stackTrace: s,
      );
    }
  }

So on my login screen I get the users email, when they click next I do get an email. I click on email link and I get sent to a browser to the playstore(I dont have my app published obviously) so it gets an error, First off its supposed to open the app if its installed which.

I switched back to the default generated deeplink that firebase give me and now I'm gettig invalid url, dynaiclink blocked when the email link routes me to the browser.

I'm pissy cause I'm only attempting this method cause the OTP system I was trying to get working is broken since they removed SafetyNet and is forcing everyone to use PlayIntegrity for the AppCheck which I also spend a few days researching trying to get working.

So any help or tips would be most appreciated. Or if someone has a updated or recent guide that actually works would be a life saver.

1

There are 1 answers

0
jcmtyler On

I don't have an answer but I can't find how to just comment on your question. I'm also struggling to get passwordless email auth to work with Firebase and Flutter. I can get the registration email, but it has an invalid link like this: https://mycustomdomain.com/?link=https://my-firebase-app.firebaseapp.com/__auth/action?apiKey%3DMY_VALID_API_KEY%26mode#3DsignIn%26oobCode%3DSEEMINGLY_VALID_CODE%26continueUrl%3Dthe.url.I.put.in.ActionCodeSettings%26lang%3Den&apn=my.android.package&amv=12

Two things stand out to me compared to other examples I can find online:

  1. This link starts with my customdomain rather than my-firebase-app.
  2. The URL encoding is inconsistent, with some & = replaced by %26 and %3D, but then towards the end there is &apn=...&amv=12.

If I manually edit this URL immediately after receiving the email to https://my-firebase-app.firebaseapp.com/__/auth/action?apiKey=MY_VALID_API_KEY&mode=signIn&oobCode=CODE_FROM_EMAIL&continueUrl=the.url.I.put.in.ActionCodeSettings&lang=en&apn=my.android.package&amv=12 and paste into the browser, both on my computer and on my Android simulator, I get redirected to the continueUrl but no message about successfully validating my email or successfully signing in. I also don't see any user account show up in the Firebase console under Authentication.