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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions