Skip to content

fix(appcheck): address review feedback on seamless debug tokens - #17003

Draft
paulb777 wants to merge 3 commits into
feat/appcheck-seamless-debug-tokensfrom
pb-appcheck-debug-token-fixes
Draft

paulb777 wants to merge 3 commits into
feat/appcheck-seamless-debug-tokensfrom
pb-appcheck-debug-token-fixes

Conversation

@paulb777

@paulb777 paulb777 commented Nov 4, 2026 •

Copy link
Copy Markdown
Member

Follow-up to #16994, based on its branch, that addresses review feedback. It can be merged into #16994 or cherry-picked.

Build plugin and script

  • The plugin never ran the generator for clients. It looked for inject_debug_token.sh under context.package.directoryURL (and xcodeProject.directoryURL), which is the client's package or project, so it always fell back to an empty stub. The generator is now embedded in the plugin.
  • Stale tokens. The CLI configuration file wasn't a build input, so a rotated token (for example, after the 403 hint's --force) wasn't picked up without a clean build. The plugin now uses a prebuild command that runs on every build and rewrites the generated file only when it changes.
  • Only the target app's token is embedded. Previously every token in the CLI configuration, including other projects' apps, was compiled into the app.
  • $XDG_CONFIG_HOME/configstore is checked before ~/.config/configstore, matching configstore. The app ID and token are validated before being written into Swift source. The python3 dependency is gone (plutil is used instead).
  • inject_debug_token.sh is kept, with the same fixes, for apps that use a Run Script build phase instead of the plugin.
  • Added a README with usage for Swift packages, Xcode targets, and Run Script phases.

Runtime

  • Don't log externally provided tokens. A failed exchange, including a transient network error, logged the token from FIREBASE_APPCHECK_DEBUG_TOKEN/AppCheckDebugToken at warning level. AppCheckCore deliberately avoids this to prevent leaking CI secrets. Only locally generated tokens are printed now; otherwise the message names the source.
  • setenv handoff to AppCheckCore. Token resolution and AppCheckCore provider creation now happen under one lock (previously resolution ran outside it, so a concurrent init could pick up another app's token). The handoff is skipped when AppCheckCore reads the same environment variable anyway. It remains for the new sources until AppCheckCore can accept a token directly; its init(...environment:) is internal today.
  • 403 detection uses the HTTP status code only. GACAppCheckHTTPError's description includes the request URL (project and app IDs) and the response body, so matching "403" in the text misclassified other errors. Its error code is 0, so the code == 403 check never matched.
  • Removed the #if DEBUG check on injected tokens. It reflects how Firebase was compiled, so zip and Carthage users (Release-built binaries) never got the injected token and saw a "SECURITY WARNING" error during Debug development. The generated class is already wrapped in #if DEBUG.
  • On macOS, the configuration file is read from the user's home directory rather than NSHomeDirectory(), which is the app container in sandboxed apps.
  • Logging: removed the duplicated [FirebaseAppCheck] prefix, log the token source at Notice level (Info isn't shown by default), and added the project and app IDs to the 403 hint.
  • Updated the FIRAppCheckDebugProvider.h docs and the CHANGELOG.

Tests

  • Clear GACAppCheckDebugToken in setUp/tearDown. It leaked between tests: stored_user_defaults_token_555 showed up in the Catalyst failures.
  • Guard the configuration file tests to simulators and macOS, matching the source. This fixes the Catalyst jobs.
  • Added tests for the logging fix, 403 detection (including errors that only mention "403"), XDG precedence, the legacy environment variable, and +tokens keyed by app ID.

Testing

  • FirebaseAppCheckUnit passes on macOS, Mac Catalyst, and iOS Simulator.
  • Plugin, tested with a sample client package:
    • Only the target app's token is embedded, and Release binaries contain no token.
    • With xcodebuild, a rotated, removed, or newly created token is picked up by the next incremental build.
    • SwiftPM CLI caches its build plan and re-runs prebuild commands only when the plan changes. This matters little, because macOS tools read the configuration file at runtime first.
  • Not tested: the XcodeBuildToolPlugin entry point on an Xcode project (non-package) target.

Open questions

  • Does firebase appcheck:debugtokens:create --project <id> --app <id> --force match the CLI?
  • Mac Catalyst is still excluded from the configuration file lookup. Is that intended?

Stop logging externally provided debug tokens when a token exchange
fails. Environment variables often hold CI secrets, and the token from
FIREBASE_APPCHECK_DEBUG_TOKEN or AppCheckDebugToken was printed at
warning level on any exchange error. Log the token source instead.

Resolve the token and create the AppCheckCore provider under one lock,
and skip the environment handoff when AppCheckCore reads the same
variable anyway. Detect HTTP 403 by status code rather than by matching
"403" in the error text, which contains the request URL and response
body. Drop the #if DEBUG check on injected tokens: it reflects how
Firebase was built, which broke zip and Carthage users, and the
generated class is already wrapped in #if DEBUG. Check XDG_CONFIG_HOME
first, like the Firebase CLI, and use the real home directory on macOS
because NSHomeDirectory() is the container in sandboxed apps.

Clear the stored debug token between tests and only run the
configuration file tests on platforms that read the file, which fixes
the Mac Catalyst jobs.
The plugin looked for inject_debug_token.sh in the client's package or
Xcode project, where it never exists, so it always generated an empty
stub. Embed the generator in the plugin as a prebuild command, which
runs on every build and so picks up a new or rotated token without a
clean build. Embed only the token for the target's app instead of every
token in the Firebase CLI configuration, validate values before writing
them into Swift source, and drop the python3 dependency.

Apply the same fixes to inject_debug_token.sh for Run Script build
phases, ship it with the pod, and document both.
@gemini-code-assist

Copy link
Copy Markdown
Contributor
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Firebase 13 no longer supports CocoaPods, so don't ship
inject_debug_token.sh with the pod. Document running the script from
the Swift package checkout instead, for apps that can't use the plugin.
@paulb777

paulb777 commented Nov 4, 2026

Copy link
Copy Markdown
Member Author

@AustinBenoit I'm still working through this - and will add you back when I'm done

@paulb777
paulb777 removed the request for review from AustinBenoit November 4, 2026 17:04
@paulb777
paulb777 marked this pull request as draft November 4, 2026 17:04
@ncooke3 ncooke3 added this to the 13.2.0 - M189 milestone Nov 5, 2026

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants