Firebase Verify Token

Firebase Verify Token

Secure, lightweight, and pure Dart solution for verifying Firebase JWT tokens.
No backend required. Supports multi-project validation.

Pub Version Pub Points Pub Likes License


✨ Features

  • 🛡️ Pure Dart: Verify tokens without exposing your private keys or using the Firebase Admin SDK.
  • 🌍 Multi-Platform: Works on Android, iOS, Web, macOS, Windows, and Linux.
  • ⏱️ Accurate Timing: Uses NTP synchronization to prevent issues with device clock drift.
  • High Performance: Caches Google's public keys for faster verification.
  • 🔐 Secure Validation:
    • Checks Signature (RSA SHA-256)
    • Validates Expiration (exp), Issued At (iat), and Auth Time (auth_time).
    • Verifies Audience (aud / Project ID) and Issuer (iss).

🚀 Getting Started

1. Install via pubspec.yaml

dependencies:
  firebase_verify_token_dart: ^2.3.0

2. Import the Package

import 'package:firebase_verify_token_dart/firebase_verify_token_dart.dart';

📖 Usage

Initialize

Set the allowed Firebase Project IDs (Audience) before verifying tokens. This is usually done in your main() or initialization logic.

void main() {
  FirebaseVerifyToken.projectIds = ['my-firebase-project-id'];
}

Verify a Token

Verify a raw JWT token string. This method is asynchronous and returns a bool.

final isValid = await FirebaseVerifyToken.verify(token);

if (isValid) {
  print("✅ Token is valid!");
} else {
  print("❌ Invalid token.");
}

Get Verification Details

Pass an optional callback to get detailed results, including the matched project ID and verification duration.

final isValid = await FirebaseVerifyToken.verify(
  token,
  onVerifyCompleted: ({required bool status, String? projectId, int? duration}) {
    if (status) {
      print("✅ Verified for project '$projectId' inside ${duration}ms");
    } else {
      print("❌ Verification failed.");
    }
  },
);

⚙️ Advanced Configuration (Thread-Safe & Offline-Ready)

You can pass advanced arguments directly to the verify method. This is perfect for high-performance backends, offline development, or multi-tenant (multi-project) systems:

final isValid = await FirebaseVerifyToken.verify(
  token,
  // 1. Thread-safe project overriding (avoid race conditions in multi-tenant backends)
  projectIds: ['my-awesome-project', 'another-tenant-project'],

  // 2. Custom clock skew leeway (default is 5 minutes)
  clockSkew: const Duration(minutes: 2),

  // 3. High-performance / offline mode (defaults to true)
  // Set to 'false' to bypass all NTP network checks and use the system clock.
  // This executes validation locally and synchronously in under 1ms!
  useNtp: false,

  onVerifyCompleted: ({required bool status, String? projectId, int? duration}) {
    print("Verification completed in ${duration}ms.");
  },
);

NTP Failover (Always Reliable)

If useNtp is set to true (the default), the package will synchronize time using a precise network clock. However, if the server is offline or UDP port 123 is blocked by a restrictive firewall, the package automatically and gracefully falls back to the system clock rather than breaking your authentication flow.

Extract Claims (Without Verification)

Sometimes you just need to read the token's content (e.g., User ID) without a full cryptographic check.

// Get User ID (sub)
final uid = FirebaseVerifyToken.getUserID(token);

// Get Project ID (aud)
final projectId = FirebaseVerifyToken.getProjectID(token);

🛠️ Advanced

Why use this over the Firebase Admin SDK? The Firebase Admin SDK requires a service account with elevated privileges, which is dangerous to use in client-side applications. This package purely verifies the token's signature using Google's public keys, making it safe for client-side use or lightweight server-side Dart applications (e.g., Dart Frog, Shelf).


🤝 Contributing

We welcome contributions!

  • 🐛 Report Issues: Submit bugs or feature requests on GitHub Issues.
  • 💡 Submit PRs: Pull Requests are welcome. Please adhere to the existing code style.

📄 License

This project is licensed under the MIT License.