Single Device Login in Flutter Using Firebase Authentication and Firestore/Realtime Database

Wed, Sep 27, 2023

Read in 2 minutes

To enforce that a user is logged in on only one device at a time using Flutter with Firebase Authentication, you can use Firebase Realtime Database or Firestore to store the user's session information. Here’s a step-by-step guide on how you can achieve this:

1. Set Up Firebase:

2. Store Session Information:

When a user logs in, generate a unique session ID and store it in Firestore/Realtime Database along with the user’s UID.

import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
// Import 'package:firebase_database/firebase_database.dart'; // For Realtime Database

final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
// final FirebaseDatabase _database = FirebaseDatabase.instance; // For Realtime Database

User? user = _auth.currentUser;

if (user != null) {
  String sessionID = _generateSessionID(); // Implement a function to generate a unique session ID.
  
  // Store the sessionID in Firestore.
  _firestore.collection('sessions').doc(user.uid).set({
    'sessionID': sessionID,
  });
  
  // Alternatively, for Realtime Database.
  // _database.reference().child('sessions/${user.uid}').set({
  //   'sessionID': sessionID,
  // });
}

3. Listen for Session Changes:

Create a listener to monitor changes to the session information. If the session ID in the database does not match the current session ID, log the user out.

StreamSubscription<DocumentSnapshot>? sessionSubscription;
// StreamSubscription<DataSnapshot>? sessionSubscription; // For Realtime Database

if (user != null) {
  // Listen for changes in Firestore.
  sessionSubscription = _firestore.collection('sessions').doc(user.uid).snapshots().listen((snapshot) {
    if (snapshot.exists) {
      String storedSessionID = snapshot.get('sessionID');
      if (storedSessionID != currentSessionID) {
        _auth.signOut();
      }
    }
  });
  
  // Alternatively, for Realtime Database.
  // sessionSubscription = _database.reference().child('sessions/${user.uid}').onValue.listen((event) {
  //   DataSnapshot snapshot = event.snapshot;
  //   String storedSessionID = snapshot.value['sessionID'];
  //   if (storedSessionID != currentSessionID) {
  //     _auth.signOut();
  //   }
  // });
}

// Make sure to cancel the subscription when it is no longer needed.
@override
void dispose() {
  sessionSubscription?.cancel();
  super.dispose();
}

4. Handle Logout and Session Cleanup:

When a user logs out, clean up the session information from the Firestore/Realtime Database.

await _auth.signOut();
// Remove the session information from Firestore/Realtime Database.
_firestore.collection('sessions').doc(user.uid).delete();
// _database.reference().child('sessions/${user.uid}').remove(); // For Realtime Database

5. Secure Access and Privacy Considerations:

This approach allows you to ensure that a user is only logged in on one device at a time by tracking session information in Firebase and actively monitoring for any discrepancies.


Shohruh AK





See Also

New App Signing feature provided by Google Play
4 Ways to Close Keyboard in Flutter App
Create Coin Toss App Using Flutter
How To Improve Your Coding Skills
Dark Sides of Being a Programmer