FirebaseAuth.NET 1.8.0

dotnet add package FirebaseAuth.NET --version 1.8.0
                    
NuGet\Install-Package FirebaseAuth.NET -Version 1.8.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FirebaseAuth.NET" Version="1.8.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FirebaseAuth.NET" Version="1.8.0" />
                    
Directory.Packages.props
<PackageReference Include="FirebaseAuth.NET" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FirebaseAuth.NET --version 1.8.0
                    
#r "nuget: FirebaseAuth.NET, 1.8.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FirebaseAuth.NET@1.8.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FirebaseAuth.NET&version=1.8.0
                    
Install as a Cake Addin
#tool nuget:?package=FirebaseAuth.NET&version=1.8.0
                    
Install as a Cake Tool

πŸ” FirebaseAuth.NET

A simple, cross-platform Firebase Authentication library for MAUI, Blazor, Console, etc. targeting .NET 8, .NET 9, or .NET 10. Supports Email + Password login, registration, password reset, token persistence with secure storage abstraction, account deletion (unregister), password change, email change flow, user profile refresh, and granular error mapping.

Current version: 1.8.0


πŸ“¦ Install from NuGet

dotnet add package FirebaseAuth.NET

NuGet: https://www.nuget.org/packages/FirebaseAuth.NET


🧱 Features

βœ… Email + Password Authentication
βœ… Registration (optional disable, sends verification email immediately on success)
βœ… Password Reset
βœ… Change Password
βœ… Start Email Change Flow (verify & change)
βœ… Refresh User Info (accounts:lookup)
βœ… Auto Token Refresh
βœ… Reusable SecureStorage abstraction
βœ… Works in MAUI, Blazor, WPF, ASP.NET, or Console apps targeting .NET 8, .NET 9, or .NET 10
βœ… Account deletion (Unregister)
βœ… Typed errors via FirebaseAuthException and AuthErrorReason
βœ… Robust Firebase error payload parsing (nested message formats)


πŸ”Ž Error Reasons Overview

AuthErrorReason includes (non-exhaustive):

  • InvalidEmailAddress, EmailExists, EmailNotFound
  • InvalidPassword, WeakPassword, InvalidLoginCredentials
  • UserDisabled, TooManyAttempts
  • InvalidIdToken, TokenExpired
  • MissingRefreshToken, InvalidRefreshToken
  • RequiresRecentLogin, OperationNotAllowed

TokenExpired vs InvalidIdToken vs Refresh Token Errors

  • TokenExpired: ID token lifetime elapsed; library attempts refresh automatically using stored refresh token. On success you transparently continue.
  • InvalidIdToken: Provided ID token rejected (revoked / changed context, e.g. after email change). Force re-login.
  • MissingRefreshToken: Refresh attempted without token (corrupt / cleared state). Force logout + re-login.
  • InvalidRefreshToken: Token revoked / malformed / deleted user. Force logout + re-login.

βš™οΈ Setup in a MAUI App

1️⃣ Create a Secure Storage Adapter

Storage/MauiSecureStorage.cs

using FirebaseAuth.NET.Storage;

namespace MyApp.Storage;

public class MauiSecureStorage : ISecureStorage
{
    public Task SetAsync(string key, string value) => SecureStorage.Default.SetAsync(key, value);
    public Task<string?> GetAsync(string key) => SecureStorage.Default.GetAsync(key);
    public void Remove(string key) => SecureStorage.Default.Remove(key);
}

2️⃣ Register Dependencies

MauiProgram.cs

using FirebaseAuth.NET.Services;
using FirebaseAuth.NET.Storage;
using MyApp.Storage;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();

        builder.Services.AddSingleton<ISecureStorage, MauiSecureStorage>();
        builder.Services.AddSingleton<IFirebaseAuthService>(sp =>
        {
            var logger = sp.GetRequiredService<ILogger<FirebaseAuthService>>();
            var storage = sp.GetRequiredService<ISecureStorage>();
            var http = new HttpClient();
            var apiKey = "YOUR_FIREBASE_API_KEY"; // from Firebase Console
            var options = new FirebaseAuthOptions
            {
                ThrowOnError = true,
                // AllowRegistration = false // optional
            };
            return new FirebaseAuthService(http, logger, storage, apiKey, options);
        });

        return builder.Build();
    }
}

3️⃣ Use It Anywhere (Example Page)

try
{
    var user = await _auth.LoginAsync("test@example.com", "password123");
    if (user != null)
        await DisplayAlert("Welcome", $"Logged in as {user.Email}", "OK");
    else
        await DisplayAlert("Error", "Login failed.", "OK");
}
catch (FirebaseAuthException ex)
{
    switch (ex.Reason)
    {
        case AuthErrorReason.InvalidEmailAddress:
            await DisplayAlert("Error", "Invalid email address.", "OK");
            break;
        case AuthErrorReason.InvalidPassword:
        case AuthErrorReason.InvalidLoginCredentials:
            await DisplayAlert("Error", "Invalid credentials.", "OK");
            break;
        case AuthErrorReason.MissingRefreshToken:
        case AuthErrorReason.InvalidRefreshToken:
            _auth.Logout();
            await DisplayAlert("Session", "Session expired. Please log in again.", "OK");
            break;
        default:
            await DisplayAlert("Error", ex.Message, "OK");
            break;
    }
}

Notes

  • Changing password requires signed-in user and may need recent login.
  • Email change flow invalidates old tokens; re-login then call RefreshUserInfoAsync().

Email Change Flow

  1. Call StartEmailChangeAsync(newEmail) to send verification link.
  2. User confirms link β‡’ Firebase updates email; old ID token may fail.
  3. Handle InvalidIdToken, MissingRefreshToken, InvalidRefreshToken by forcing re-login.
  4. Call RefreshUserInfoAsync() to obtain updated email.

Refresh Token Failure Handling

FirebaseUser? current = null;
try
{
    current = await _auth.GetCurrentUserAsync();
}
catch (FirebaseAuthException ex) when (
    ex.Reason == AuthErrorReason.TokenExpired ||
    ex.Reason == AuthErrorReason.InvalidIdToken ||
    ex.Reason == AuthErrorReason.InvalidRefreshToken ||
    ex.Reason == AuthErrorReason.MissingRefreshToken)
{
    _auth.Logout();
}

If refresh fails (missing/invalid) require manual login.


4️⃣ Logout Example

_auth.Logout();

πŸ§ͺ Full Console App Example

using FirebaseAuth.NET.Services;
using FirebaseAuth.NET.Storage;
using Microsoft.Extensions.Logging;

// Minimal secure storage implementation (file-based) for demo
public class FileSecureStorage : ISecureStorage
{
    private readonly string _dir = Path.Combine(AppContext.BaseDirectory, "authstore");
    public FileSecureStorage() => Directory.CreateDirectory(_dir);
    public Task SetAsync(string key, string value)
    {
        File.WriteAllText(Path.Combine(_dir, key), value);
        return Task.CompletedTask;
    }
    public Task<string?> GetAsync(string key)
    {
        var path = Path.Combine(_dir, key);
        return Task.FromResult(File.Exists(path) ? File.ReadAllText(path) : null);
    }
    public void Remove(string key)
    {
        var path = Path.Combine(_dir, key);
        if (File.Exists(path)) File.Delete(path);
    }
}

var loggerFactory = LoggerFactory.Create(b => b.AddConsole());
var logger = loggerFactory.CreateLogger<FirebaseAuthService>();
var http = new HttpClient();
var storage = new FileSecureStorage();
var options = new FirebaseAuthOptions { ThrowOnError = true };
var auth = new FirebaseAuthService(http, logger, storage, "YOUR_FIREBASE_API_KEY", options);

try
{
    // Register (if enabled)
    var registered = await auth.RegisterAsync("user@example.com", "StrongP@ssw0rd!");
    Console.WriteLine($"Registered: {registered?.Email}");
}
catch (FirebaseAuthException ex)
{
    Console.WriteLine($"Registration failed ({ex.Reason}): {ex.Message}");
}

// Login
FirebaseUser? user = null;
try
{
    user = await auth.LoginAsync("user@example.com", "StrongP@ssw0rd!");
    Console.WriteLine($"Logged in: {user?.Email}");
}
catch (FirebaseAuthException ex)
{
    Console.WriteLine($"Login failed ({ex.Reason}): {ex.Message}");
}

// Start email change
var started = await auth.StartEmailChangeAsync("new.email@example.com", canHandleCodeInApp: true);
Console.WriteLine(started ? "Email change verification sent." : "Failed to send email change link.");
Console.WriteLine("(Simulate user clicking verification link in mailbox...)\n");

// Pretend some time passes & tokens may be invalid now
await Task.Delay(TimeSpan.FromSeconds(2));

try
{
    var refreshed = await auth.RefreshUserInfoAsync();
    Console.WriteLine(refreshed != null ? $"Refreshed email: {refreshed.Email}" : "Refresh failed");
}
catch (FirebaseAuthException ex) when (
    ex.Reason == AuthErrorReason.InvalidIdToken ||
    ex.Reason == AuthErrorReason.InvalidRefreshToken ||
    ex.Reason == AuthErrorReason.MissingRefreshToken)
{
    Console.WriteLine($"Session invalid ({ex.Reason}). Re-login required.");
    auth.Logout();
    user = await auth.LoginAsync("new.email@example.com", "StrongP@ssw0rd!");
    Console.WriteLine($"Re-logged in: {user?.Email}");
    var updated = await auth.RefreshUserInfoAsync();
    Console.WriteLine(updated != null ? $"Updated email after reauth: {updated.Email}" : "Refresh user info failed");
}

// Change password
var changedPwd = await auth.ChangePasswordAsync("An0therStr0ngP@ss!");
Console.WriteLine(changedPwd ? "Password changed." : "Password change failed.");

// Unregister
var deleted = await auth.UnregisterAsync();
Console.WriteLine(deleted ? "Account deleted." : "Account deletion failed.");

🧩 Advanced

  • Provide custom ISecureStorage (KeyChain/Keystore, DPAPI, file, memory for tests).
  • Disable registration: new FirebaseAuthOptions { AllowRegistration = false }.
  • Fine-tune error strategy: ThrowOnError = true to receive typed exceptions instead of null/false.
  • Wrap service behind your own auth facade for app-specific logic.

🌐 Cross-platform notes

  • Uses ILogger and Polly for transient retry (timeouts, 5xx, 429).
  • No platform-specific code in core library (pure .NET).
  • Works in Blazor WASM (Google endpoints support CORS).

πŸ“˜ API Surface

Key methods: LoginAsync, RegisterAsync, GetCurrentUserAsync, SendPasswordResetEmailAsync, StartEmailChangeAsync, RefreshUserInfoAsync, ChangePasswordAsync, UnregisterAsync, Logout.


πŸ§‘β€πŸ’» Author

Imre SzΓΌcs – MIT License


🌟 Contribute

Issues & PRs welcome: https://github.com/szucsim/FirebaseAuth.NET/issues

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.8.0 104 5/21/2026
1.7.1 516 11/20/2025
1.7.0 426 11/18/2025
1.6.0 249 11/16/2025
1.5.0 170 11/15/2025
1.4.4 302 11/12/2025
1.4.3 236 11/10/2025
1.4.0 194 10/25/2025
1.3.2 133 10/24/2025
1.3.1 137 10/24/2025
1.3.0 130 10/24/2025
1.2.0 139 10/24/2025
1.1.0 200 10/23/2025
1.0.1 204 10/21/2025
1.0.0 186 10/21/2025

1.8.0: RegisterAsync now sends Firebase email verification immediately after successful registration.
     1.7.1: Added mappings for MISSING_REFRESH_TOKEN and INVALID_REFRESH_TOKEN; clarified docs about token vs refresh token invalidation and email change reauthentication flow.
     1.7.0: Expands framework support, the package now targets .NET 8, .NET 9, and .NET 10.
     1.6.0: Added StartEmailChangeAsync (verify and change email) and RefreshUserInfoAsync.
     1.5.0: Removed ChangeEmailAsync API and feature. Updated docs and tests accordingly.
     1.4.4: Fix to throw correct exceptions.
     1.4.3: Internal validation improvements for error mapping.
     1.4.2: Improved parsing of nested Firebase error payloads (e.g. "INVALID_ARGUMENT: INVALID_LOGIN_CREDENTIALS") so LoginAsync now throws AuthErrorReason.InvalidLoginCredentials instead of Unknown.
     1.4.1: Map and throw INVALID_LOGIN_CREDENTIALS during LoginAsync when ThrowOnError is enabled.
     1.4.0: Added ChangeEmailAsync to allow changing the signed-in user's email; updated README; includes XML documentation.