Skip to main content

Overview

The AuthService class provides comprehensive authentication functionality for the Flutter application, including email/password authentication, Google Sign-In, user profile management, and user search capabilities. Location: lib/services/auth_service.dart

Dependencies

  • firebase_auth - Firebase Authentication
  • cloud_firestore - Firestore database
  • firebase_storage - Firebase Storage for profile images
  • google_sign_in - Google Sign-In integration
  • logger - Logging functionality

Authentication Methods

registerWithEmailAndPassword

Registers a new user with email and password credentials.
Future<User?> registerWithEmailAndPassword(String email, String password)
email
String
required
The user’s email address
password
String
required
The user’s password
User?
Future<User?>
Returns a User object if registration is successful, or null if an error occurs

Example

final authService = AuthService();
final user = await authService.registerWithEmailAndPassword(
  '[email protected]',
  'securePassword123'
);

if (user != null) {
  print('Registration successful: ${user.uid}');
} else {
  print('Registration failed');
}

Error Handling

  • Returns null if registration fails
  • Errors are logged using the Logger instance
  • Common errors include: invalid email format, weak password, email already in use

signInWithEmailAndPassword

Authenticates an existing user with email and password.
Future<User?> signInWithEmailAndPassword(String email, String password)
email
String
required
The user’s email address
password
String
required
The user’s password
User?
Future<User?>
Returns a User object if sign-in is successful, or null if an error occurs

Example

final authService = AuthService();
final user = await authService.signInWithEmailAndPassword(
  '[email protected]',
  'securePassword123'
);

if (user != null) {
  print('Sign-in successful: ${user.uid}');
} else {
  print('Invalid credentials');
}

Error Handling

  • Returns null if authentication fails
  • Errors are logged automatically
  • Common errors include: user not found, wrong password, too many requests

signInWithGoogle

Authenticates a user using Google Sign-In.
Future<User?> signInWithGoogle()
User?
Future<User?>
Returns a User object if sign-in is successful, or null if the user cancels or an error occurs

Behavior

  • Opens Google Sign-In dialog
  • Automatically creates user profile in Firestore if it doesn’t exist
  • Uses displayName from Google account as the user’s name
  • Returns null if user cancels the sign-in dialog

Example

final authService = AuthService();
final user = await authService.signInWithGoogle();

if (user != null) {
  print('Google sign-in successful: ${user.displayName}');
} else {
  print('Sign-in cancelled or failed');
}

Firestore Integration


signOut

Signs out the current user from both Firebase Auth and Google Sign-In.
Future<void> signOut()

Example

final authService = AuthService();
await authService.signOut();
print('User signed out successfully');

Profile Management

saveUserProfile

Saves or updates user profile information in Firestore, including optional profile image upload to Firebase Storage.
Future<void> saveUserProfile(
  String uid,
  String name,
  String surname,
  File? profileImage
)
uid
String
required
The user’s unique identifier from Firebase Auth
name
String
required
The user’s first name
surname
String
required
The user’s surname/last name
profileImage
File?
Optional profile image file. If provided, it will be uploaded to Firebase Storage at profileImages/{uid}.jpg

Firestore Document Structure

{
  "name": "John",
  "surname": "Doe",
  "photoUrl": "https://firebasestorage.googleapis.com/..."
}

Example

import 'dart:io';

final authService = AuthService();
final user = authService.currentUser;

if (user != null) {
  final imageFile = File('/path/to/profile.jpg');
  await authService.saveUserProfile(
    user.uid,
    'John',
    'Doe',
    imageFile
  );
}

Storage Behavior


getUserProfile

Retrieves user profile data from Firestore.
Future<Map<String, dynamic>?> getUserProfile(String uid)
uid
String
required
The user’s unique identifier
Map<String, dynamic>?
Future<Map<String, dynamic>?>
Returns a map containing user profile data, or null if the profile doesn’t exist or an error occurs

Example

final authService = AuthService();
final profile = await authService.getUserProfile('user_uid_123');

if (profile != null) {
  print('Name: ${profile['name']}');
  print('Surname: ${profile['surname']}');
  print('Photo URL: ${profile['photoUrl']}');
}

searchUsersByName

Searches for users by name using Firestore queries.
Future<List<UserProfile>> searchUsersByName(String name)
name
String
required
The name or partial name to search for
List<UserProfile>
Future<List<UserProfile>>
Returns a list of UserProfile objects matching the search query. Returns empty list if no matches found or error occurs.

Search Behavior

  • Uses Firestore range queries with \uf8ff character for prefix matching
  • Searches the name field in the users collection
  • Case-sensitive search

Example

final authService = AuthService();
final users = await authService.searchUsersByName('John');

for (var user in users) {
  print('Found user: ${user.name}');
}

searchUsersByNameOrEmail

Searches for users by either name or email address.
Future<List<UserProfile>> searchUsersByNameOrEmail(String query)
query
String
required
The search query to match against name or email fields
List<UserProfile>
Future<List<UserProfile>>
Returns a combined list of UserProfile objects matching either name or email. Returns empty list if no matches found or error occurs.

Search Strategy

Example

final authService = AuthService();
final users = await authService.searchUsersByNameOrEmail('john');

print('Found ${users.length} users matching "john"');
for (var user in users) {
  print('${user.name} - ${user.email}');
}

Properties

currentUser

Gets the currently authenticated user.
User? get currentUser
User?
User?
Returns the current User object if authenticated, or null if no user is signed in

Example

final authService = AuthService();
final user = authService.currentUser;

if (user != null) {
  print('Current user: ${user.email}');
} else {
  print('No user signed in');
}

displayName

Gets the display name of the current user.
String? get displayName
String?
String?
Returns the display name, or null if not set or no user is signed in

photoURL

Gets the photo URL of the current user.
String? get photoURL
String?
String?
Returns the photo URL, or null if not set or no user is signed in

Error Handling Best Practices

All methods in AuthService handle errors gracefully:
  • Methods return null or empty lists on failure
  • Errors are automatically logged using Logger
  • No exceptions are thrown to the caller
  • Always check return values before proceeding

Example Error Handling

final authService = AuthService();

// Check for null returns
final user = await authService.signInWithEmailAndPassword(
  email,
  password
);

if (user == null) {
  // Handle authentication failure
  showErrorDialog('Invalid credentials');
  return;
}

// Proceed with authenticated user
navigateToHome();

Build docs developers (and LLMs) love