You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Refactor: Consolidate JWKS fetching and expose a unified JWT verifier for downstream SDKs #299
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
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.
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.
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.
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.
Activity
demolaf commentedon Jul 10, 2026
@kevmoo currently looking into this, i've self-assigned but if it's quite urgent I can unassign too.
kevmoo commentedon Jul 10, 2026
demolaf commentedon Jul 13, 2026
@kevmoo so either googleapis.dart or google-cloud-dart?
kevmoo commentedon Jul 13, 2026
Maybe
google-cloud-dart. Is my thought. Need to discuss/design. CC @brianquinlanbrianquinlan commentedon Jul 16, 2026
Is this something that should live in
package:webcryptoor something that can be built with the primitives inpackage:webcrypto?kevmoo commentedon Jul 17, 2026
@brianquinlan thinking the crypto bits go into pkg:webcripto and the JWT bits go into a new package
kevmoo commentedon Jul 17, 2026
...a new package under google-cloud-dart
brianquinlan commentedon Jul 17, 2026
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 topackage:google_cloudmight 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
kevmoo commentedon Jul 20, 2026
Likely in google-cloud-dart somewhere. I need to write up my thoughts here!