Flutter: way to validate one sort of google account? - email

I'm building an app in flutter (latest build) for students on the university. every student has its own email and password (ex. s2170456#student.utwente.nl), which is integrated in google, so everyone is able to see notifications in Gmail.
This does also mean; if you want to log in with google, your studentEmail is an option to do so. I want to implement a google log-in feature where only student of the university (with their email sXXXXXXX#student.utwente.nl) are able to login.
My question is: is there a way to filter on the google login email? I thought about using normal email login and use RegEx to validate, but this means student should firstly signup. I would like to skip the whole sign-up and let the students use their already owned student email to signin.
it should look something like this (if it is even possible) VV
Widget googleLogin () {
googleLogin button()
if(googlelogin.email == sXXXXXXX#student.utwente.nl)
log user in;
} else {
return error message('invalid email')
}
I want this to be able to only register and login user with student email.

You can use google sign in integration like this.
GoogleSignInAccount _currentUser;
then in init state:-
#override
void initState() {
super.initState();
_googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount account) {
setState(() {
_currentUser = account;
print("User Name ${_currentUser.displayName}");
print("User Email ${_currentUser.email}");
});
if (_currentUser != null) {
var socialData = SocialData(
_currentUser.displayName, "", _currentUser.email, LoginType.GOOGLE);
_startHomeScreen(socialData);
} else {
_showError('Error, Please try again later');
}
});
}
on successful login, this will execute:-
_startHomeScreen(SocialData data) {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return Home(socialData: data);
}));
}
Future<void> _handleSignIn() async {
try {
await _googleSignIn.signIn();
} catch (error) {
print(error);
}
}
Call _handleSignIn() on click of google sign in button.

The solution is to let anyone sign in but block the users from using the app unless they are using the university mail
void handleUser(FirebaseUser user) {
if(user.email==sXXXXXXX#student.utwente.nl) {
// handle sign in and UI changes
} else {
print('The user is not allowed');
}
}

Related

How to link phone number to already logged in email user which is using firebase

I want to link the already login user who has login from their email id when starting the website but after completing the signup process I want to add the phone number of the user but I am getting an error as firebase creates a new id every time when creating a new id after the phone OTP verification.
So, after some digging, I found out that there is a way to LINK already logged in the user with an email with a phone number.
But, the function is not working for me
here is my code for adding a phone number and then linking it with current user credentials.
sendOTP(String phoneNumber) async {
this.phoneNumber = phoneNumber;
FirebaseAuth auth = FirebaseAuth.instance;
print('${phoneCode}');
ConfirmationResult confirmationResult =
await auth.signInWithPhoneNumber('+${phoneCode}${phoneNumber}');
if (kDebugMode) {
print("OTP send to +${phoneCode} ${phoneNumber}");
}
return confirmationResult;
}
authenticateMe(ConfirmationResult confirmationResult, String otp) async {
UserCredential userCredential = await confirmationResult.confirm(otp);
signIn(AuthCredential userCredential) async {
//now link these credentials with the existing user
UserCredential? linkauthresult =
await existingUser?.linkWithCredential(userCredential);
print('linked');
}
firebaseOtp = otp;
}
here is my User existingUser = FirebaseAuth.instance.currentUser!; variable which is i am calling in init state
#override
void initState() {
super.initState();
existingUser;
print('this is current user from otp_container ${existingUser}');
}
and here is my button onPressed function
onPressed: () {
authenticateMe(
temp,
otpCodeController.text,
);
Future.delayed(const Duration(seconds: 3))
.then((value) {
if (!mounted) {
const CircularProgressIndicator();
}
setState(() {
if (otpCodeController.text ==
firebaseOtp) {
isAnimatedContainer =
!isAnimatedContainer;
} else {
setState(() {
verifyOtpcheck = !verifyOtpcheck;
});
}
});
});
},
and I am working on flutter web.

Do not send gmail notification when user trying to change their email from the app firebase flutter

I have my change email page in my app. And when I changed it. Firebase always send me gmail notifications like this for ex.
Is there anyway to disable it?
code:
_resetEmail(
String email,
String userUid,
) async {
try {
UserCredential;
await auth.currentUser!.updateEmail(email);
await Database().email(email, FirebaseAuth.instance.currentUser!.uid);
} on FirebaseAuthException {
print('error');
}
}

Flutter uni_links duplicate the app every time a link is clicked

I am implementing a password recovery function based on the url sent to the email. Opening the app based on that url was successful. But instead of directly opening the required page in the app that is in the background, it duplicates the app. Although it still leads me to the password recovery page, now there will be 2 same apps running side by side
Procedure
Enter your email to send the password reset link
Click submit
Open the email containing the recovery link
Duplicate the app and open a recovery password page
Things what happen
Splash screen, first page open in the app, I am trying to do as instructed from uni_links package but still no success. Currently the function getInitialLink has the effect of opening the app based on the recovery link
class SplashController extends GetxController {
final SharedPreferencesHelper _helper = Get.find<SharedPreferencesHelper>();
late StreamSubscription sub;
#override
void onReady() async {
super.onReady();
await checkToken();
}
Future<void> checkToken() async {
await Future.delayed(Duration(seconds: 3));
var token = _helper.getToken();
if (token == null) {
Get.offNamed(Routes.LOGIN);
} else {
Get.offNamed(Routes.MAIN);
}
}
#override
void onInit() {
super.onInit();
initUniLinks();
}
Future<Null> initUniLinks() async {
// Platform messages may fail, so we use a try/catch PlatformException.
try {
String? initialLink = await getInitialLink();
if (initialLink != null) {
print("okay man");
Get.toNamed(Routes.RECOVERY);
}
sub = getLinksStream().listen((link) {
}, onError: (err) {
});
} on PlatformException {
// Handle exception by warning the user their action did not succeed
// return?
}
}
}
I found the solution, actually this answer is already on Stackoverflow, and it's really simple.
In the AndroidManifest.xml file of the app. Find "android:launchMode" and change its old value to singleTask. And here is the result
android:launchMode="singleTask"

linkWithCredential and Flutter Web with Apple

I have a use case where a user, on Flutter Web, needs to link an Apple auth with their existing account, and the email may not match.
However, the only available method for Flutter Web Apple Authentication is signInWithPopUp. If the user's apple email is different from the User firebase account email, a new firebase account is created, and a user is returned, short circuiting the process of linking, this creates a new account in firebase, and I'm unable to linkWithCredential.
My method to try to link accounts is as follows:
Future<String> linkWithAppleWeb() async {
try {
final User user = _auth.currentUser!;
final provider = OAuthProvider("apple.com")
..addScope('email')
..addScope('name');
await _auth.signInWithPopup(provider).then((appleCredential) async {
final authCredential = appleCredential.credential;
await user.linkWithCredential(authCredential!).then((result) {
DatabaseService().updateUserSocialAuth(user.uid, 'apple');
return 'Success';
}).catchError((e) {
return 'Error: $e';
});
});
} catch (e) {
return 'Error: $e';
}
return 'Success';
}
As you would expect, my project starts with Streaming a User Object, and when the pop up signs in, it returns the new user, which rebuilds the entire project. Is there a way to authenticate an apple user without returning a new user? I can link a google or phone authorization method fine. It's apple that is problematic. I don't fully understand why Google doesn't break in the same way, other than Firebase put in the work to ensure the functionality of linking for GoogleSignIn().signIn() I'm not using other social auth methods, and I don't use password/email.
This method is not documented in the Flutter Fire Docs, but works perfectly:
Future<String> linkWithAppleWeb() async {
try {
final User user = _auth.currentUser!;
final provider = OAuthProvider("apple.com")
..addScope('email')
..addScope('name');
await user.linkWithPopup(provider).then((result) {
DatabaseService().updateUserSocialAuth(user.uid, 'apple');
return 'Success';
}).catchError((e) {
return 'Error: $e';
});
} catch (e) {
debugPrint('auth linkWithGoogle error: ${e.toString()}');
return 'Error: $e';
}
return 'Success';
}

Flutter: Firebase user's name doesn't get updated when user logs in for the first time

I am trying to fetch a user's ID when a person is logged in with their firebase account. When I try to login a new user for the first time, I can fetch their id however the user's details only reflect after the person navigates from one page to another using the navigation bar. Is there a way I can get rid of that? I want the user's display name to reflect as soon as they create a new account.
This is my current code that I call in my initState()
getCurrentUser() async {
try {
final user = await _auth.currentUser();
if (user != null) {
setState(() {
loggedInUser = user;
id = user.uid;
username = user.displayName;
});
}
} catch (e) {
print(e);
}
}