Skip to content

feat(app_check): support CLI-provisioned debug tokens on Apple and Web - #18947

Open
AustinBenoit wants to merge 3 commits into
mainfrom
feat/appcheck-seamless-debug-tokens
Open

AustinBenoit wants to merge 3 commits into
mainfrom
feat/appcheck-seamless-debug-tokens

Conversation

@AustinBenoit

@AustinBenoit AustinBenoit commented Nov 11, 2026 •

Copy link
Copy Markdown

Description

Enables firebase_app_check on Apple (iOS/macOS) and Web to preserve and use CLI-provisioned App Check debug tokens without manual copy-pasting or overriding injected tokens:

  • Apple (packages/firebase_app_check/firebase_app_check Swift plugin):
    • Switches environment variable configuration for explicit Dart debugToken values to AppCheckDebugToken (set only when non-empty) and restores any prior value via defer after AppCheckDebugProvider(app: app) initializes.
    • No longer prints the debug token from the plugin. The native SDK logs a locally generated token with instructions for registering it, and does not log a token provisioned by the Firebase CLI.
  • Web (packages/firebase_app_check/firebase_app_check_web):
    • Extracts @visibleForTesting configureWebDebugTokenGlobal(String? debugToken) and uses it in getAppCheckInstance for WebDebugProvider.
    • When an explicit non-empty debugToken is provided, sets FIREBASE_APPCHECK_DEBUG_TOKEN to that token. Otherwise, preserves an existing non-empty string already set on globalContext.FIREBASE_APPCHECK_DEBUG_TOKEN instead of overwriting it with true, falling back to true only when unset, empty, or non-string.
    • Adds Chrome unit tests in test/firebase_app_check_web_test.dart covering pre-set token preservation, explicit override, and true fallback.

Testing

  • Ran locally (Linux):
    • dart format --output=none --set-exit-if-changed (firebase_app_check_web)
    • dart analyze --fatal-infos (firebase_app_check_web: no issues)
    • flutter test --platform chrome packages/firebase_app_check/firebase_app_check_web/test/firebase_app_check_web_test.dart (10/10 passed)
  • Apple Swift changes (FirebaseAppCheckPlugin.swift, symlinked to macOS) rely on GitHub Actions macOS/iOS CI for Xcode compilation and testing.

Related Issues

Related upstream seamless debug token work: firebase/firebase-tools#11418, firebase/firebase-ios-sdk#17017.

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]).
This will ensure a smooth and quick review process. Updating the pubspec.yaml and changelogs is not required.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • My PR includes unit or integration tests for all changed/updated/fixed behaviors (See Contributor Guide).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (melos run analyze) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require plugin users to manually update their apps to accommodate your change?

  • Yes, this is a breaking change.
  • No, this is not a breaking change.

Prepared with AI coding agents (Google-internal, built on Jetski) and opened by @AustinBenoit.

- Apple (iOS/macOS): temporarily set `AppCheckDebugToken` instead of
  `FIRAAppCheckDebugToken` when Dart supplies a non-empty `debugToken`
  and restore it via `defer`; under `#if DEBUG` log
  `currentDebugToken()` rather than `localDebugToken()` when no Dart
  token is supplied so CLI-provisioned Simulator tokens are preserved.
- Web: extract `configureWebDebugTokenGlobal` to preserve an existing
  non-empty `globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN` string when
  `WebDebugProvider.debugToken` is null or empty, and add Chrome tests.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Firebase App Check debug token handling for iOS and Web platforms. On iOS, it updates the environment variable key to AppCheckDebugToken, manages its state using a defer block to restore any prior token, and limits debug token printing to debug builds. On Web, it introduces a helper function configureWebDebugTokenGlobal to manage the global FIREBASE_APPCHECK_DEBUG_TOKEN variable and adds corresponding unit tests. The review feedback suggests improving the Swift implementation by using optional chaining to avoid variable shadowing and simplify compatibility, and simplifying the Dart code by removing a redundant isDefinedAndNotNull check.

Comment on lines +374 to +376
if debugToken?.isEmpty ?? true, let debugProvider {
print("Firebase App Check Debug Token: \(debugProvider.currentDebugToken())")
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

Using optional chaining with debugProvider?.currentDebugToken() is cleaner, avoids shadowing the debugProvider variable, and is fully backward-compatible with older Swift versions (avoiding Swift 5.7's implicit optional binding shorthand).

Suggested change
if debugToken?.isEmpty ?? true, let debugProvider {
print("Firebase App Check Debug Token: \(debugProvider.currentDebugToken())")
}
if debugToken?.isEmpty ?? true, let token = debugProvider?.currentDebugToken() {
print("Firebase App Check Debug Token: \(token)")
}

Comment on lines +36 to +41
if (existing != null &&
existing.isDefinedAndNotNull &&
existing.isA<JSString>() &&
(existing as JSString).toDart.isNotEmpty) {
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

The check existing.isDefinedAndNotNull is redundant because existing != null already ensures that the value is neither Dart null nor JS null/undefined (since getProperty returns Dart null for JS null or undefined). We can simplify this condition.

  if (existing != null &&
      existing.isA<JSString>() &&
      (existing as JSString).toDart.isNotEmpty) {
    return;
  }

@cynthiajoan

Copy link
Copy Markdown
Contributor

delegateProvider = debugProvider
#if DEBUG
if debugToken?.isEmpty ?? true, let debugProvider {
print("Firebase App Check Debug Token: \(debugProvider.currentDebugToken())")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to print the CLI debugToken? Is this behavior by design?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in 0363091. The plugin no longer prints the debug token: the native SDK already logs a locally generated token with the instructions for registering it, and it does not log a token provisioned by the Firebase CLI, so printing it here was not intended.

@SelaseKay SelaseKay left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @AustinBenoit, thanks for the PR.

The web change looks good.

On Apple, the CLI token is read from ~/.config/configstore/firebase-appcheck.json by firebase/firebase-ios-sdk#17017. That commit is on main and is not in the SDKs this repo pin (Swift Package Manager 13.1.1). AppCheckDebugProvider in those versions still uses the environment variable or a generated UserDefaults token, so merging this as it stands leaves the Simulator on the old flow. The same upstream change also compiles that file lookup out on macOS.

I'd wait for a release that contains that commit.

The plugin printed the debug token itself when Dart supplied none. The
native SDK already logs a locally generated token with instructions for
registering it, and deliberately does not log a token provisioned by the
Firebase CLI, so the plugin's print would have exposed that one.
@AustinBenoit

Copy link
Copy Markdown
Author

@SelaseKay firebase-ios-sdk 13.2.0 was released today and includes firebase/firebase-ios-sdk#17017, the CLI debug token lookup on Simulator.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants