Skip to content

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

Open

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

  1. added theissue type on Jul 8, 2026
  2. self-assigned this
    on Jul 10, 2026
  3. demolaf commented on Jul 10, 2026

    @demolaf
    Member

    @kevmoo currently looking into this, i've self-assigned but if it's quite urgent I can unassign too.

  4. kevmoo commented on Jul 10, 2026

    @kevmoo
    ContributorAuthor
  5. removed their assignment
    on Jul 13, 2026
  6. demolaf commented on Jul 13, 2026

    @demolaf
    Member
  7. kevmoo commented on Jul 13, 2026

    @kevmoo
    ContributorAuthor

    Maybe google-cloud-dart. Is my thought. Need to discuss/design. CC @brianquinlan

  8. brianquinlan commented on Jul 16, 2026

    @brianquinlan
    Contributor

    Is this something that should live in package:webcrypto or something that can be built with the primitives in package:webcrypto?

  9. kevmoo commented on Jul 17, 2026

    @kevmoo
    ContributorAuthor

    @brianquinlan thinking the crypto bits go into pkg:webcripto and the JWT bits go into a new package

  10. kevmoo commented on Jul 17, 2026

    @kevmoo
    ContributorAuthor

    ...a new package under google-cloud-dart

  11. brianquinlan commented on Jul 17, 2026

    @brianquinlan
    Contributor

    A new package? Or in package:google_cloud? If the functionality is relatively simple and doesn't introduce a bunch of new dependencies then adding it to package:google_cloud might be the most practical approach.

    Do you know how the other cloud languages approach this? For Python, JWT functionality seems to live in the auth package: https://google-auth.readthedocs.io/en/latest/index.html

  12. kevmoo commented on Jul 20, 2026

    @kevmoo
    ContributorAuthor

    Likely in google-cloud-dart somewhere. I need to write up my thoughts here!

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