firebase / firebase/firebase-admin-dart

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

Open
#299 9 comments 0 reactions 0 assignees View on GitHub
keep-open package:firebase_admin_sdk
Dominant language
Dart
Stars
177
Forks
70
Avg merge
5d 14h
Merged PRs (30d)
6

Description

### 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`](https://github.com/firebase/firebase-admin-dart/blob/main/packages/firebase_admin_sdk/lib/src/utils/jwt.dart#L60-L120) (for X.509 PEM certs) and [`JwksFetcher`](https://github.com/firebase/firebase-admin-dart/blob/main/packages/firebase_admin_sdk/lib/src/utils/jwt.dart#L122-L171) (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`](https://github.com/firebase/firebase-functions-dart/blob/main/lib/src/identity/token_verifier.dart#L149-L202) 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`](https://github.com/firebase/firebase-admin-dart/blob/main/packages/firebase_admin_sdk/lib/src/auth/token_verifier.dart) nor [`AppCheckTokenVerifier`](https://github.com/firebase/firebase-admin-dart/blob/main/packages/firebase_admin_sdk/lib/src/app_check/token_verifier.dart) 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`).
* [ ] 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`.

Contributor guide

Open the contributing guide

Research direction

Start by reading packages/firebase_admin_sdk/lib/src/utils/jwt.dart, especially UrlKeyFetcher, JwksFetcher, and PublicKeySignatureVerifier, then compare the token verifiers and firebase_functions/lib/src/identity/token_verifier.dart. Map the cache, clock-skew, and audience-validation differences before choosing a shared API. Done means downstream SDKs can use one reusable verifier without duplicating key fetching or claim validation.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart
Domain
authentication, backend, security
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.