I have been trying to get the sign-in by email link to work. After enabling this in Firebase, I created two custom actions.
The first action is to send the sign-in link after the user has entered their email:
// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/backend/schema/structs/index.dart';
import '/backend/schema/enums/enums.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/actions/index.dart'; // Imports other custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom action code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!
import 'package:firebase_auth/firebase_auth.dart';
Future sendDynamicSignInLink(String email) async {
// Function to send a request to Firebase for an email signin link.
// Get the current URL
Uri currentUri = Uri.base;
print('Current URL: $currentUri'); // Debug print
// Construct the new URL by replacing the path with '/complete-signin'
Uri newUri = currentUri.replace(path: 'completeSignIn');
// Function to request Firebase to send an email sign-in link
try {
await FirebaseAuth.instance.sendSignInLinkToEmail(
email: email,
actionCodeSettings: ActionCodeSettings(
url: newUri.toString(),
handleCodeInApp: true,
),
);
} catch (e) {
throw Exception('Failed to send sign-in link: $e');
}
}
The second action is to log the user in after they click the link (email also saved as a state variable for later):
// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/backend/schema/structs/index.dart';
import '/backend/schema/enums/enums.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/actions/index.dart'; // Imports other custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom action code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!
import 'package:firebase_auth/firebase_auth.dart';
Future completeSignIn() async {
Uri currentUri = Uri.base;
String emailLink =
currentUri.toString(); // Use the full URL for the email link
print('Current URI: $currentUri');
if (emailLink.isEmpty) {
print('No email link found in URL');
throw Exception('No email link found in URL');
}
final FirebaseAuth _auth = FirebaseAuth.instance;
if (_auth.isSignInWithEmailLink(emailLink)) {
try {
String? email = FFAppState().userEmail;
if (email != null && email.isNotEmpty) {
print('Signing in with email: $email');
UserCredential userCredential =
await _auth.signInWithEmailLink(email: email, emailLink: emailLink);
AuthCredential? credential = userCredential.credential;
if (credential == null) {
throw Exception('Failed to get AuthCredential from UserCredential');
}
await _auth.currentUser!.linkWithCredential(credential);
print(
'Successfully signed in: ${FirebaseAuth.instance.currentUser?.email}');
} else {
print('Email not found in app state');
throw Exception('Email not found. Please enter your email address.');
}
} catch (e) {
print('Failed to sign in: $e');
throw Exception('Failed to sign in: $e');
}
} else {
print('Email link is not valid');
throw Exception('Email link is not valid');
}
}
This appears to work. The user receives the email, and it looks like they have successfully logged into Firebase (a successfully signed-in message is shown). However, FlutterFlow does not recognise the user as logged in.
This is very close to working. I'm hoping someone can point me in the right direction for having FlutterFlow recognise the user as logged in once they have been verified/signed in by Firebase.