Skip to content

Refactor: Consolidate JWKS fetching and expose a unified JWT verifier for downstream SDKs #299

Description

@kevmoo

Background

Across firebase_admin_sdk and downstream consumers like firebase_functions (which depends on firebase_admin_sdk), there are multiple overlapping implementations of JWT signature verification, JWKS / X.509 certificate fetching, and public key caching.

Currently, firebase_admin_sdk maintains both UrlKeyFetcher (for X.509 PEM certs) and JwksFetcher (for JSON Web Key Sets) in lib/src/utils/jwt.dart.

Current Inconsistencies & Duplication

  1. Inconsistent Key Caching & TTLs:
    • UrlKeyFetcher parses HTTP Cache-Control: max-age headers via string splitting and tracks expiration via DateTime.
    • JwksFetcher ignores HTTP Cache-Control headers entirely, hardcoding a static 6-hour TTL (6 * 60 * 60 * 1000) and tracking expiration via epoch integer comparison.
    • Meanwhile, downstream in firebase_functions, AuthBlockingTokenVerifier hand-rolled a third key fetcher (_getGoogleKeys()) that parses Cache-Control: max-age via regex and defaults to a 1-hour TTL.
  2. Inconsistent Clock Skew and Claim Validation:
    • Neither FirebaseTokenVerifier nor AppCheckTokenVerifier supports clock-skew tolerance on timestamps (iat, exp). However, Auth Blocking events in firebase_functions require a 5-minute clock skew on iat.
    • Audience (aud) claim handling varies: ID token verification assumes String, App Check assumes List, and downstream functions must handle both String and List polymorphically.
  3. Lack of Reusability for Downstream Packages:
    • Because PublicKeySignatureVerifier and JwksFetcher are either marked @internal or lack configuration ergonomics (v3 JWKS endpoints, clock skew, polymorphic audience matching), firebase_functions was forced to duplicate the entire JWT verification stack from scratch.

Proposed Action Items

  • Unify JwksFetcher and UrlKeyFetcher to share standard HTTP Cache-Control: max-age parsing (with a sensible default fallback like 1 hour).
  • Support configurable clock-skew tolerance (e.g., an optional Duration clockSkew parameter) in PublicKeySignatureVerifier and claim validation.
  • Support polymorphic audience (aud) matching (String vs. List<String>).
  • Expose a clean, reusable JWT verification primitive (or align with an upstream foundation like google_cloud_server_auth) so downstream SDKs like firebase_functions can delete their custom verifiers and rely directly on firebase_admin_sdk.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions