how to login once and stay logged in until you log out? - firebase

I couldn't figure it out. as i restart the app (if i am signed in or not) it goes to the login page, can you guys help me out on this. i am new to flutter so detailed instructions will be appreciated. Thanks
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: (googleSignIn.isSignedIn() != null) ? MainPage() : LoginPage(),
routes: {
'upload': (context) => ItemInput(),
'toyota': (context) => Toyota(),
},
));
}
Auth.dart
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
Future<User> signInWithGoogle() async {
final GoogleSignInAccount googleSignInAcount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAcount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
idToken: googleSignInAuthentication.idToken,
accessToken: googleSignInAuthentication.accessToken);
final UserCredential authResult =
await _auth.signInWithCredential(credential);
final User user = authResult.user;
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final User currentUser = _auth.currentUser;
assert(currentUser.uid == user.uid);
return user;
}
void signOutGoogle() async {
await googleSignIn.signOut();
}
Login.dart
void click() {
signInWithGoogle().then((user) => {
this.user = user,
Navigator.push(
context, MaterialPageRoute(builder: (context) => MainPage()))
});
}
RaisedButton.icon(
onPressed: () async {
click();
},
label: Text(
'Sign-up with Google ',
)),

Firebase automatically restores the user's authentication state when the app is restarted. So you'd typically detect whether the user is already signed in, and then navigate to the post-login screen when they are.
According to the documentation on authentication state you can get the authentication state with:
FirebaseAuth.instance
.authStateChanges()
.listen((User user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
// ... navigate to post-login screen
}
});

One way to do it is by using shared preference, see, https://pub.dev/packages/shared_preferences
When the signin is successful do,
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool("isLoggedIn", true);
This will store a boolean value that you use to check if the user is signed in or not. It will be saved even after the app is closed unless you uninstall or clear app data.
and in the main.dart use that stored prefs value to check if the user is already signed in or not by doing -
SharedPreferences prefs = await SharedPreferences.getInstance();
bool isLoggedIn = prefs.getBool("isLoggedIn");
Use the isLoggedIn value, navigate the user to either Login Screen or Home Screen, and use it to perform other logic.

Related

How to access the uid of a google-registered user for our Firestore collection?

I am creating a flutter app. The point is that in my database, I want the users to be recognized with their uid. For users registered with email & password, there is no problem because I can easily access to their uid with user.uid. But when the user registers with his google account, I don't know how to access to his uid. I just know how to access to his id which is different by running _user.id. How to access the user's uid in this case? Here's the code:
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
final googleSignIn = GoogleSignIn();
GoogleSignInAccount? _user;
// create user object based on firebase user
Users? _userFromFirebaseUser(User? user) {
return user != null ? Users(uid: user.uid) : null;
}
// auth change user stream
Stream<Users?> get user {
return _auth.authStateChanges().map(_userFromFirebaseUser);
}
//register with email & psswrd
Future registerWithEmailAndPassword(String email, String password) async {
try {
UserCredential result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
User? user = result.user;
await DatabaseService(uid: user!.uid).updateUserData('new user', 0);
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
Future signInithGoogle() async {
try {
final result = await googleSignIn.signIn();
if (result == null)
return await DatabaseService(uid: _user!.id)
.updateUserData('new user', 0);
_user = result;
final googleAuth = await result.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await _auth.signInWithCredential(credential);
} catch (e) {}
}
The 'updateUserData' function creates a new record for the user when he registers. The DatabaseService class contains all the functions related to Firestore. here it is:
class DatabaseService {
final String uid;
DatabaseService({required this.uid});
// collection reference
final CollectionReference userCollection =
FirebaseFirestore.instance.collection('users');
Future updateUserData(String name, int points) async {
return await userCollection.doc(uid).set({
'name': name,
'points': points,
});
}
}
When you call await _auth.signInWithCredential(credential), you get back a UserCredential, which is the same that you get back from await FirebaseAuth.instance.signInWithEmailAndPassword(...).
So you can get the UID from the UserCredential in both cases with:
var credentials = await _auth.signInWithCredential(credential);
var uid = credentials.user!.uid
If you're listening to auth state changes, then that will fire when you sign in with any provider, and you'll get a User? object. So you can get the UID from that with:
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User ${user.uid} is signed in!');
}
});

Firebase auth flutter

For user logged in
Future<String> signInWithGoogle() async {
final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
final AuthResult authResult = await _auth.signInWithCredential(credential);
final FirebaseUser user = authResult.user;
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
if(authResult.additionalUserInfo.isNewUser == true){
InsertNewUserDetails(user.displayName,user.email,user.photoUrl,user.phoneNumber);
}
if(authResult.user != null){
email = user.email;
name = user.displayName;
imageUrl =user.photoUrl;
globalInstance.isLoggedIn = true;
print(globalInstance.isLoggedIn);
}
return 'signInWithGoogle succeeded: $user';
}
This first time sign in Loginpage checking for is logged account
class MyApp extends StatelessWidget {
#override
String strinbggg;
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.teal,
body: StreamBuilder<FirebaseUser>(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData && (!snapshot.data.isAnonymous)) {
// return Text('${snapshot.hasData}');
return Homepage();
} else {
// return SafeArea(
// maintainBottomViewPadding: true,
// child: Text('aasdasdfasfdh : ${snapshot.data.email}',style: TextStyle(color: Colors.black54),));
return LoginPage();
}
},
),
),
);
}
}
When first time login with google its working. When i was close application and start again it will redirecting to the homepage fine but user profile details like displayName , email are returning null value
signInwithgoogle() is use for the first time login that store the user details in firestore and user details set from here
MyApp is starting point of application that will check is user is already logged in
I would suggest, you check the user is already signed in or not using the method
bool isSignedIn = await _googleSignIn.isSignedIn();
and if the user is signed in, then get the credentials using
user = await _auth.currentUser();
when you start the app. In case you are not logged in, show login page. Any example would be something like below
final auth = FirebaseAuth.instance;
class MyApp extends StatelessWidget {
#override
String strinbggg;
Widget build(BuildContext context) {
return MaterialApp(
home: (_isSignedIn() == true ? new Homepage() : new LoginPage()));
}
bool _isSignedIn() async {
bool isSignedIn = await _googleSignIn.isSignedIn();
if(isSignedIn){
GoogleSignInAccount user = await auth.currentUser;
//You can store this in your state.
}
return !(user == null && auth.currentUser == null);
}
}
Please note this is a in editor composed code, not tested, you will have to make adjustments.

When I log out of application and again login it takes me to homepage automatically without asking for choosing an account

I have created login application, using flutter and firebase.
i am doing google login. I have 2 pages login.dart and homepage.dart where everything happens. When i click on login button it asks for choose an account and take me to homepage, but when i logout, and again try to login it takes me automatically to homepage, but i want it to ask again for choosing an account.
I have created signout() function in loginpage itself, where I have written the code for the rest of the authentication, but when I call this function in homepage.dart in logout button, it wont come.
Code for Login Authentication in loginpage.dart
class _LoginPageState extends State<LoginPage> {
String _email;
String _password;
//google sign in
final GoogleSignIn googleSignIn= GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;
Future<FirebaseUser> _signIn() async{
//GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
GoogleSignInAccount googleUser = await googleSignIn.signIn();
GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: googleAuth.idToken,
accessToken: googleAuth.accessToken,
);
final FirebaseUser user = await _auth.signInWithCredential(credential);
print("User Name: ${user.displayName}");
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
Navigator.of(context).pushReplacementNamed('/homepage');
}
Future<void> signOut() async {
return googleSignIn.signOut();
}
code for log out button in homepage.dart
MaterialButton(
onPressed: () {
signOut
FirebaseAuth.instance.signOut().then((value) {
Navigator.of(context).pushReplacementNamed('/landingpage');
})
.catchError((e){
print(e);
});
},
child: Text('Log Out'),
)
Please Help me out

flutter firebase login not redirect after signInWithCredential

I'm using flutter and firebase auth with google sign in.
specifically I'm referring to this Tutorial
but, in that case no redirect after login success.
in my case, i want to redirect after login success.
I have made like this on AuthService
Future<FirebaseUser> googleSignIn() async {
loading.add(true);
GoogleSignInAccount googleUser = await _googleSignIn.signIn();
GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
FirebaseUser user = await _auth.signInWithCredential(credential);
updateUserData(user);
print("signed in : " + user.displayName);
loading.add(false);
return user;
}
initState
void initState() {
super.initState();
authService.profile.listen((state) {
print("ini statenya $state");
});
}
and button
CupertinoButton(
color: const Color(0xFFdd4b39),
child: const Text('Google'),
onPressed: () => authService.googleSignIn().then((user) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BeforeDashboard(
uuid: user,
)),
);
})),
But, it only work when i use debug mode. and not redirect on release mode.
After choose account popup will be gone but not redirect on dashboard

Flutter Authentication sign in & sign out with Google from logged screen to login screen

today I tried to build 2 screens "login with GG" and "logout redirect to login screen". Succeed! But when I log in again, Previous gg account logged in immediately without requiring sign-in popup. On my device remember logged account. How to sign out completely and sign-in again with the other accounts. Here my code:
I have 'the home page with login with google' and 'home-center page with signout button'. Besides, I have api.dart to log in and log out, and the main page using routes to 2 pages.
- Main Page:
routes: {
"home-page": (context) => MyHomePage(),
"game-center": (context) => GameCenterPage(),
},
home: MyHomePage(),
- Api.dart:
class FBApi {
static FirebaseAuth _auth = FirebaseAuth.instance;
static GoogleSignIn _googleSignIn = GoogleSignIn();
FirebaseUser firebaseUser;
FBApi(FirebaseUser user) {
this.firebaseUser = user;
}
static Future<FBApi> signInWithGoogle() async {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final FirebaseUser user = await _auth.signInWithGoogle(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
assert(user.email != null);
assert(user.displayName != null);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
return FBApi(user);
}
static Future<void> signOut() async {
await _auth.signOut().then((_) {
print("***** log out...what the hell?");
// Navigator.of(context).pushNamedAndRemoveUntil("/login",
ModalRoute.withName("/home"));
});
}
}
- gameCenter.dart:
onPressed: () async {
_signOut();
Navigator.of(context).pushNamedAndRemoveUntil("home-page", ModalRoute.withName("game-center"));
},
- home.dart
class MyHomePage extends StatelessWidget {
Future<bool> _loginUser() async {
final api = await FBApi.signInWithGoogle();
if (api != null) {
return true;
} else {
return false;
}
}
...
I experienced a similar issue this weekend and resolved it by also signing out of GoogleSignIn - however I'm not sure if this is the correct approach as I would have expected FirbaseAuth to auto sign out of all providers.
static Future<void> signOut() async {
await _auth.signOut().then((_) {
//try the following
_googleSignIn.signOut();
//try the following
Navigator.of(context).pushNamedAndRemoveUntil("/login", ModalRoute.withName("/home"));
});
if you are having issue with the login popup for Google SignIn do this after signout call
Navigator.pushReplacement(
(context), MaterialPageRoute(builder: (context) => widget));
User gets signed out from Firebase, but not from Google.
So next time you already have a user signed in and that is returned by GoogleSignIn().
You need to sign out from Google as well. Following works perfectly for me:
Future signOut() async {
try {
await _fireBaseAuthInstance.signOut();
await _googleSignInInstance.signOut();
} catch (e) {
print('Failed to signOut' + e.toString());
}
}

Resources