Firebase Authentication (Swift/iOS)

authenticationSwiftiOSFirebaseGooglemobileOAuthphone authenticationanonymous authentication

Library

Firebase Authentication (Swift/iOS)

Overview

Firebase Authentication for iOS (Swift) is a comprehensive authentication SDK for iOS applications provided by Google's Firebase platform. As of 2025, it supports complete integration via Swift Package Manager and provides unified authentication experiences for iOS, macOS, tvOS, and watchOS applications. Supporting a wide range of authentication methods including email & password, OAuth (Google, Apple, Facebook, etc.), phone number authentication, and anonymous authentication, it works with both SwiftUI and UIKit. Complying with Apple's latest security guidelines, it provides enterprise-level user management features in conjunction with Firebase Console.

Details

Firebase Authentication for iOS (Swift) is an authentication solution optimized for the Apple ecosystem. Firebase Auth iOS SDK v10.x series is fully integrated with Swift Concurrency, enabling natural authentication implementation for iOS developers. The Auth class serves as the central entry point for authentication APIs, managing authentication state per FirebaseApp instance. With modular design, only necessary features can be selected and integrated, enabling bundle size optimization. Integration with Keychain Services automatically persists user credentials across app launches, providing seamless user experience. AuthDataResult and User objects provide structured access to user information and metadata.

Key Features

  • Swift Concurrency Integration: Modern asynchronous processing with async/await and actor isolation
  • Comprehensive Provider Support: 10+ authentication providers (Google, Apple, Facebook, etc.)
  • Automatic Token Management: Automatic ID token refresh and keychain persistence
  • Multi-Factor Authentication: Advanced security with SMS and TOTP
  • App Check Integration: App instance authenticity verification
  • Combine Support: Reactive programming with FirebaseCombineSwift

Advantages and Disadvantages

Advantages

  • Complete support for Swift Concurrency and async/await enables modern, readable code implementation
  • Seamless integration with Firebase ecosystem including Firestore, Cloud Functions, etc.
  • Automatic token refresh and keychain management significantly reduces developer implementation burden
  • Comprehensive OAuth provider support offers convenient diverse authentication options for users
  • High development efficiency through Google's extensive documentation and community support
  • Enterprise-level security features (multi-factor authentication, App Check) provided as standard

Disadvantages

  • Dependency on Google Firebase ecosystem creates vendor lock-in risk
  • Network connectivity required, with limitations on offline authentication features
  • Large SDK size due to comprehensive features affects app bundle size
  • Constraints exist for authentication flows requiring advanced customization
  • Complex initial setup requiring both Firebase project and iOS app configuration
  • Additional SDK integration required for some authentication providers (Facebook SDK, etc.)

Reference Pages

Usage Examples

Basic Setup and Firebase Configuration

// AppDelegate.swift - Firebase initialization
import UIKit
import Firebase

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication, 
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Initialize Firebase using configuration file (GoogleService-Info.plist)
        FirebaseApp.configure()
        return true
    }
}

// ContentView.swift - Basic authentication management
import SwiftUI
import Firebase
import FirebaseAuth

@MainActor
class AuthenticationManager: ObservableObject {
    @Published var user: User?
    @Published var isSignedIn = false
    
    private var authStateHandle: AuthStateDidChangeListenerHandle?
    
    init() {
        // Start monitoring authentication state
        setupAuthStateListener()
    }
    
    deinit {
        // Remove authentication state listener
        if let handle = authStateHandle {
            Auth.auth().removeStateDidChangeListener(handle)
        }
    }
    
    private func setupAuthStateListener() {
        authStateHandle = Auth.auth().addStateDidChangeListener { [weak self] _, user in
            Task { @MainActor in
                self?.user = user
                self?.isSignedIn = user != nil
            }
        }
    }
    
    // Get current user information
    func getCurrentUser() -> User? {
        return Auth.auth().currentUser
    }
    
    // Get user's ID token
    func getIDToken(forcingRefresh: Bool = false) async throws -> String? {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        return try await user.getIDToken(forcingRefresh: forcingRefresh)
    }
}

enum AuthenticationError: Error, LocalizedError {
    case userNotSignedIn
    case authenticationFailed
    case invalidCredentials
    
    var errorDescription: String? {
        switch self {
        case .userNotSignedIn:
            return "User is not signed in"
        case .authenticationFailed:
            return "Authentication failed"
        case .invalidCredentials:
            return "Invalid credentials"
        }
    }
}

Email & Password Authentication Implementation

// EmailAuthService.swift - Email authentication service
import Foundation
import FirebaseAuth

class EmailAuthService: ObservableObject {
    
    // User registration (async/await version)
    func createUser(email: String, password: String) async throws -> AuthDataResult {
        do {
            let authResult = try await Auth.auth().createUser(withEmail: email, password: password)
            
            // Send email verification immediately after registration
            try await sendEmailVerification()
            
            return authResult
        } catch let error as NSError {
            throw mapAuthError(error)
        }
    }
    
    // User sign-in
    func signIn(email: String, password: String) async throws -> AuthDataResult {
        do {
            let authResult = try await Auth.auth().signIn(withEmail: email, password: password)
            
            // Check email verification
            if let user = authResult.user, !user.isEmailVerified {
                print("Warning: Email not verified")
            }
            
            return authResult
        } catch let error as NSError {
            throw mapAuthError(error)
        }
    }
    
    // Send email verification
    func sendEmailVerification() async throws {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        try await user.sendEmailVerification()
    }
    
    // Password reset
    func sendPasswordReset(email: String) async throws {
        try await Auth.auth().sendPasswordReset(withEmail: email)
    }
    
    // Update email address (requires reauthentication)
    func updateEmail(newEmail: String, currentPassword: String) async throws {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        // Reauthentication required for security-sensitive operations
        let credential = EmailAuthProvider.credential(withEmail: user.email ?? "", password: currentPassword)
        try await user.reauthenticate(with: credential)
        
        // Update email address
        try await user.sendEmailVerification(beforeUpdatingEmail: newEmail)
    }
    
    // Update password
    func updatePassword(currentPassword: String, newPassword: String) async throws {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        // Reauthentication
        let credential = EmailAuthProvider.credential(withEmail: user.email ?? "", password: currentPassword)
        try await user.reauthenticate(with: credential)
        
        // Update password
        try await user.updatePassword(to: newPassword)
    }
    
    // Sign out
    func signOut() throws {
        try Auth.auth().signOut()
    }
    
    // Error mapping
    private func mapAuthError(_ error: NSError) -> Error {
        guard let errorCode = AuthErrorCode(rawValue: error.code) else {
            return AuthenticationError.authenticationFailed
        }
        
        switch errorCode {
        case .emailAlreadyInUse:
            return NSError(domain: "Auth", code: 1, userInfo: [NSLocalizedDescriptionKey: "This email address is already in use"])
        case .weakPassword:
            return NSError(domain: "Auth", code: 2, userInfo: [NSLocalizedDescriptionKey: "Password is too weak"])
        case .invalidEmail:
            return NSError(domain: "Auth", code: 3, userInfo: [NSLocalizedDescriptionKey: "Invalid email address"])
        case .userNotFound:
            return NSError(domain: "Auth", code: 4, userInfo: [NSLocalizedDescriptionKey: "User not found"])
        case .wrongPassword:
            return NSError(domain: "Auth", code: 5, userInfo: [NSLocalizedDescriptionKey: "Wrong password"])
        default:
            return AuthenticationError.authenticationFailed
        }
    }
}

// SwiftUI usage example
struct LoginView: View {
    @StateObject private var authService = EmailAuthService()
    @State private var email = ""
    @State private var password = ""
    @State private var isSignUp = false
    @State private var errorMessage = ""
    @State private var isLoading = false
    
    var body: some View {
        VStack(spacing: 20) {
            TextField("Email Address", text: $email)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .autocapitalization(.none)
            
            SecureField("Password", text: $password)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            
            if !errorMessage.isEmpty {
                Text(errorMessage)
                    .foregroundColor(.red)
                    .font(.caption)
            }
            
            Button(action: performAuthentication) {
                Text(isSignUp ? "Create Account" : "Sign In")
                    .frame(maxWidth: .infinity)
            }
            .buttonStyle(.borderedProminent)
            .disabled(isLoading)
            
            Button("Forgot Password?") {
                Task {
                    try? await authService.sendPasswordReset(email: email)
                }
            }
            .font(.caption)
            
            Toggle("Create New Account", isOn: $isSignUp)
        }
        .padding()
    }
    
    private func performAuthentication() {
        Task {
            isLoading = true
            errorMessage = ""
            
            do {
                if isSignUp {
                    _ = try await authService.createUser(email: email, password: password)
                } else {
                    _ = try await authService.signIn(email: email, password: password)
                }
            } catch {
                errorMessage = error.localizedDescription
            }
            
            isLoading = false
        }
    }
}

Social Authentication (Google & Apple) Implementation

// SocialAuthService.swift - Social authentication service
import Foundation
import FirebaseAuth
import GoogleSignIn
import AuthenticationServices

class SocialAuthService: NSObject, ObservableObject {
    
    // MARK: - Google Sign-In
    func signInWithGoogle() async throws -> AuthDataResult {
        // Check Google Sign-In configuration
        guard let clientID = FirebaseApp.app()?.options.clientID else {
            throw NSError(domain: "GoogleSignIn", code: -1, userInfo: [NSLocalizedDescriptionKey: "Google Client ID not found"])
        }
        
        // Google Sign-In configuration
        GIDSignIn.sharedInstance.configuration = GIDConfiguration(clientID: clientID)
        
        // Execute on main thread for UI access
        guard let presentingViewController = await UIApplication.shared.windows.first?.rootViewController else {
            throw NSError(domain: "GoogleSignIn", code: -2, userInfo: [NSLocalizedDescriptionKey: "Root view controller not found"])
        }
        
        // Execute Google Sign-In
        let result = try await GIDSignIn.sharedInstance.signIn(withPresenting: presentingViewController)
        let user = result.user
        
        guard let idToken = user.idToken?.tokenString else {
            throw NSError(domain: "GoogleSignIn", code: -3, userInfo: [NSLocalizedDescriptionKey: "ID token not found"])
        }
        
        // Create Firebase credential
        let credential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: user.accessToken.tokenString)
        
        // Execute Firebase authentication
        return try await Auth.auth().signIn(with: credential)
    }
    
    // MARK: - Apple Sign-In
    func signInWithApple() async throws -> AuthDataResult {
        return try await withCheckedThrowingContinuation { continuation in
            let request = ASAuthorizationAppleIDProvider().createRequest()
            request.requestedScopes = [.fullName, .email]
            
            let authorizationController = ASAuthorizationController(authorizationRequests: [request])
            authorizationController.delegate = AppleSignInDelegate(continuation: continuation)
            authorizationController.presentationContextProvider = self
            authorizationController.performRequests()
        }
    }
    
    // MARK: - Facebook Sign-In (Facebook SDK required)
    func signInWithFacebook() async throws -> AuthDataResult {
        // Facebook SDK implementation required
        // Add pod 'FBSDKLoginKit' to Podfile
        throw NSError(domain: "FacebookSignIn", code: -1, userInfo: [NSLocalizedDescriptionKey: "Facebook SDK integration required"])
    }
    
    // MARK: - Anonymous Authentication
    func signInAnonymously() async throws -> AuthDataResult {
        return try await Auth.auth().signInAnonymously()
    }
    
    // MARK: - Account Linking
    func linkAccount(with credential: AuthCredential) async throws -> AuthDataResult {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        return try await user.link(with: credential)
    }
    
    // MARK: - Provider Removal
    func unlink(provider: String) async throws -> User {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        return try await user.unlink(fromProvider: provider)
    }
}

// Apple Sign-In Delegate
class AppleSignInDelegate: NSObject, ASAuthorizationControllerDelegate {
    private let continuation: CheckedContinuation<AuthDataResult, Error>
    
    init(continuation: CheckedContinuation<AuthDataResult, Error>) {
        self.continuation = continuation
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
            Task {
                do {
                    let authResult = try await processAppleCredential(appleIDCredential)
                    continuation.resume(returning: authResult)
                } catch {
                    continuation.resume(throwing: error)
                }
            }
        }
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        continuation.resume(throwing: error)
    }
    
    private func processAppleCredential(_ credential: ASAuthorizationAppleIDCredential) async throws -> AuthDataResult {
        guard let nonce = generateNonce() else {
            throw NSError(domain: "AppleSignIn", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unable to generate nonce"])
        }
        
        guard let appleIDToken = credential.identityToken,
              let idTokenString = String(data: appleIDToken, encoding: .utf8) else {
            throw NSError(domain: "AppleSignIn", code: -2, userInfo: [NSLocalizedDescriptionKey: "Unable to fetch identity token"])
        }
        
        let firebaseCredential = OAuthProvider.credential(withProviderID: "apple.com",
                                                           idToken: idTokenString,
                                                           rawNonce: nonce)
        
        return try await Auth.auth().signIn(with: firebaseCredential)
    }
    
    private func generateNonce() -> String? {
        // Random nonce generation (implementation required)
        return UUID().uuidString
    }
}

// Presentation Context Provider
extension SocialAuthService: ASAuthorizationControllerPresentationContextProviding {
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        return UIApplication.shared.windows.first { $0.isKeyWindow } ?? UIWindow()
    }
}

Phone Number Authentication and Multi-Factor Authentication

// PhoneAuthService.swift - Phone number authentication service
import Foundation
import FirebaseAuth

class PhoneAuthService: ObservableObject {
    @Published var verificationID: String?
    @Published var isCodeSent = false
    
    // Send phone number verification code
    func sendVerificationCode(phoneNumber: String) async throws {
        // reCAPTCHA authentication (required in production)
        let verificationID = try await PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil)
        
        await MainActor.run {
            self.verificationID = verificationID
            self.isCodeSent = true
        }
    }
    
    // Verify code and sign in
    func verifyAndSignIn(verificationCode: String) async throws -> AuthDataResult {
        guard let verificationID = verificationID else {
            throw NSError(domain: "PhoneAuth", code: -1, userInfo: [NSLocalizedDescriptionKey: "Verification ID not found"])
        }
        
        let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID, verificationCode: verificationCode)
        return try await Auth.auth().signIn(with: credential)
    }
    
    // Link phone number to existing account
    func linkPhoneNumber(verificationCode: String) async throws -> AuthDataResult {
        guard let user = Auth.auth().currentUser,
              let verificationID = verificationID else {
            throw AuthenticationError.userNotSignedIn
        }
        
        let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID, verificationCode: verificationCode)
        return try await user.link(with: credential)
    }
}

// MultiFactorAuthService.swift - Multi-factor authentication service
class MultiFactorAuthService: ObservableObject {
    
    // Enroll multi-factor authentication
    func enrollMultiFactor(phoneNumber: String) async throws {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        // Start multi-factor authentication session
        let session = try await user.multiFactor.session()
        
        // Add second factor via phone number
        let verificationID = try await PhoneAuthProvider.provider().verifyPhoneNumber(withMultiFactorInfo: nil, multiFactorSession: session)
        
        // Verification code input needs separate implementation
        // self.verificationID = verificationID
    }
    
    // Complete MFA enrollment
    func finalizeMFAEnrollment(verificationCode: String, verificationID: String, displayName: String?) async throws {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID, verificationCode: verificationCode)
        let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
        
        try await user.multiFactor.enroll(with: assertion, displayName: displayName)
    }
    
    // Resolve MFA sign-in
    func resolveMFASignIn(resolver: MultiFactorResolver, verificationCode: String, verificationID: String) async throws -> AuthDataResult {
        let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID, verificationCode: verificationCode)
        let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
        
        return try await resolver.resolveSignIn(with: assertion)
    }
    
    // Unenroll multi-factor authentication
    func unenrollMultiFactor(factorInfo: MultiFactorInfo) async throws {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        try await user.multiFactor.unenroll(with: factorInfo)
    }
}

Combine Framework Integration and Reactive Authentication

// ReactiveAuthService.swift - Combine integrated authentication service
import Foundation
import Combine
import FirebaseAuth
import FirebaseCombineSwift

class ReactiveAuthService: ObservableObject {
    @Published var authState: AuthState = .unauthenticated
    @Published var currentUser: User?
    
    private var cancellables = Set<AnyCancellable>()
    
    enum AuthState {
        case loading
        case authenticated(User)
        case unauthenticated
        case error(Error)
    }
    
    init() {
        // Monitor Firebase Auth state changes with Combine
        Auth.auth().authStateDidChangePublisher()
            .map { user in
                if let user = user {
                    return AuthState.authenticated(user)
                } else {
                    return AuthState.unauthenticated
                }
            }
            .receive(on: DispatchQueue.main)
            .assign(to: \.authState, on: self)
            .store(in: &cancellables)
        
        // Monitor user information
        Auth.auth().authStateDidChangePublisher()
            .receive(on: DispatchQueue.main)
            .assign(to: \.currentUser, on: self)
            .store(in: &cancellables)
    }
    
    // Anonymous sign-in Combine version
    func signInAnonymously() -> AnyPublisher<AuthDataResult, Error> {
        Auth.auth().signInAnonymously()
    }
    
    // Email & password sign-in Combine version
    func signIn(email: String, password: String) -> AnyPublisher<AuthDataResult, Error> {
        Auth.auth().signIn(withEmail: email, password: password)
    }
    
    // User creation Combine version
    func createUser(email: String, password: String) -> AnyPublisher<AuthDataResult, Error> {
        Auth.auth().createUser(withEmail: email, password: password)
    }
    
    // User information update Combine chain
    func updateUserProfile(displayName: String?, photoURL: URL?) -> AnyPublisher<Void, Error> {
        guard let user = Auth.auth().currentUser else {
            return Fail(error: AuthenticationError.userNotSignedIn)
                .eraseToAnyPublisher()
        }
        
        let changeRequest = user.createProfileChangeRequest()
        changeRequest.displayName = displayName
        changeRequest.photoURL = photoURL
        
        return changeRequest.commitChanges()
    }
    
    // ID token retrieval with automatic refresh
    func getIDTokenPublisher(forcingRefresh: Bool = false) -> AnyPublisher<String, Error> {
        guard let user = Auth.auth().currentUser else {
            return Fail(error: AuthenticationError.userNotSignedIn)
                .eraseToAnyPublisher()
        }
        
        return user.getIDToken(forcingRefresh: forcingRefresh)
    }
    
    // Authentication flow chain example
    func completeRegistrationFlow(email: String, password: String, displayName: String) -> AnyPublisher<User, Error> {
        createUser(email: email, password: password)
            .flatMap { authResult -> AnyPublisher<Void, Error> in
                // Update profile
                return self.updateUserProfile(displayName: displayName, photoURL: nil)
            }
            .flatMap { _ -> AnyPublisher<Void, Error> in
                // Send email verification
                guard let user = Auth.auth().currentUser else {
                    return Fail(error: AuthenticationError.userNotSignedIn)
                        .eraseToAnyPublisher()
                }
                return user.sendEmailVerification()
            }
            .map { _ in
                // Finally return user object
                Auth.auth().currentUser!
            }
            .eraseToAnyPublisher()
    }
    
    // Error handling and retry
    func signInWithRetry(email: String, password: String, maxRetries: Int = 3) -> AnyPublisher<AuthDataResult, Error> {
        signIn(email: email, password: password)
            .retry(maxRetries)
            .catch { error -> AnyPublisher<AuthDataResult, Error> in
                // Fallback to anonymous login for specific errors
                if let authError = error as NSError?, authError.code == AuthErrorCode.userNotFound.rawValue {
                    return self.signInAnonymously()
                }
                return Fail(error: error).eraseToAnyPublisher()
            }
            .eraseToAnyPublisher()
    }
}

// SwiftUI + Combine usage example
struct CombineAuthView: View {
    @StateObject private var authService = ReactiveAuthService()
    @State private var email = ""
    @State private var password = ""
    @State private var displayName = ""
    private var cancellables = Set<AnyCancellable>()
    
    var body: some View {
        VStack {
            switch authService.authState {
            case .loading:
                ProgressView("Authenticating...")
            case .authenticated(let user):
                Text("Welcome, \(user.displayName ?? "User")")
                Button("Sign Out") {
                    try? Auth.auth().signOut()
                }
            case .unauthenticated:
                loginForm
            case .error(let error):
                Text("Error: \(error.localizedDescription)")
                    .foregroundColor(.red)
            }
        }
    }
    
    private var loginForm: some View {
        VStack {
            TextField("Email Address", text: $email)
            SecureField("Password", text: $password)
            TextField("Display Name", text: $displayName)
            
            Button("Register") {
                authService.completeRegistrationFlow(email: email, password: password, displayName: displayName)
                    .receive(on: DispatchQueue.main)
                    .sink(
                        receiveCompletion: { completion in
                            if case .failure(let error) = completion {
                                print("Registration error: \(error)")
                            }
                        },
                        receiveValue: { user in
                            print("Registration successful: \(user.uid)")
                        }
                    )
                    .store(in: &cancellables)
            }
        }
    }
}

Security Features and Token Management

// SecurityManager.swift - Security management
import Foundation
import FirebaseAuth
import FirebaseAppCheck

class SecurityManager: ObservableObject {
    
    init() {
        // App Check configuration (production environment)
        configureAppCheck()
    }
    
    private func configureAppCheck() {
        #if DEBUG
        // Use debug provider in development environment
        let providerFactory = AppCheckDebugProviderFactory()
        AppCheck.setAppCheckProviderFactory(providerFactory)
        #else
        // Use App Attest (iOS 14.0+) or Device Check in production
        if #available(iOS 14.0, *) {
            let providerFactory = AppAttestProviderFactory()
            AppCheck.setAppCheckProviderFactory(providerFactory)
        } else {
            let providerFactory = DeviceCheckProviderFactory()
            AppCheck.setAppCheckProviderFactory(providerFactory)
        }
        #endif
    }
    
    // Secure ID token retrieval
    func getSecureIDToken() async throws -> String {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        // Get latest token with forced refresh
        let idToken = try await user.getIDToken(forcingRefresh: true)
        
        // Basic token validation
        try validateTokenStructure(idToken)
        
        return idToken
    }
    
    private func validateTokenStructure(_ token: String) throws {
        let parts = token.components(separatedBy: ".")
        guard parts.count == 3 else {
            throw NSError(domain: "TokenValidation", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid JWT structure"])
        }
    }
    
    // Check user account security status
    func checkAccountSecurity() async throws -> SecurityStatus {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        // Get latest user information
        try await user.reload()
        
        var issues: [SecurityIssue] = []
        
        // Check email verification
        if !user.isEmailVerified {
            issues.append(.emailNotVerified)
        }
        
        // Check multi-factor authentication
        if user.multiFactor.enrolledFactors.isEmpty {
            issues.append(.noMultiFactorAuth)
        }
        
        // Check password strength (based on last sign-in time)
        if let metadata = user.metadata {
            let daysSinceLastSignIn = Date().timeIntervalSince(metadata.lastSignInDate ?? Date()) / (24 * 60 * 60)
            if daysSinceLastSignIn > 90 {
                issues.append(.longTimeSinceLastSignIn)
            }
        }
        
        return SecurityStatus(issues: issues)
    }
    
    // Emergency account protection
    func emergencyAccountProtection() async throws {
        guard let user = Auth.auth().currentUser else {
            throw AuthenticationError.userNotSignedIn
        }
        
        // Sign out from all devices (token invalidation)
        try await user.getIDToken(forcingRefresh: true)
        
        // Send password reset email
        if let email = user.email {
            try await Auth.auth().sendPasswordReset(withEmail: email)
        }
        
        // End current session
        try Auth.auth().signOut()
    }
    
    // Get custom claims
    func getCustomClaims() async throws -> [String: Any] {
        let idTokenResult = try await Auth.auth().currentUser?.getIDTokenResult(forcingRefresh: true)
        return idTokenResult?.claims ?? [:]
    }
}

struct SecurityStatus {
    let issues: [SecurityIssue]
    
    var isSecure: Bool {
        return issues.isEmpty
    }
    
    var riskLevel: RiskLevel {
        switch issues.count {
        case 0:
            return .low
        case 1...2:
            return .medium
        default:
            return .high
        }
    }
}

enum SecurityIssue: CaseIterable {
    case emailNotVerified
    case noMultiFactorAuth
    case longTimeSinceLastSignIn
    case suspiciousActivity
    
    var description: String {
        switch self {
        case .emailNotVerified:
            return "Email address is not verified"
        case .noMultiFactorAuth:
            return "Multi-factor authentication is not set up"
        case .longTimeSinceLastSignIn:
            return "Has not signed in for a long time"
        case .suspiciousActivity:
            return "Suspicious activity detected"
        }
    }
}

enum RiskLevel {
    case low, medium, high
    
    var color: UIColor {
        switch self {
        case .low:
            return .systemGreen
        case .medium:
            return .systemOrange
        case .high:
            return .systemRed
        }
    }
}