Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Docs

on:
push:
branches: [main]
paths:
- "docs/**"
- ".github/workflows/docs.yml"
pull_request:
paths:
- "docs/**"
- ".github/workflows/docs.yml"
workflow_dispatch:

# Pinned to the version the book was written against: mdBook has made breaking
# changes between minor releases, so a floating version can fail a build that
# works locally. Bump it deliberately, after running `mdbook build docs`.
env:
MDBOOK_VERSION: "0.5.4"

permissions:
contents: read

jobs:
build:
name: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- name: Install mdBook
run: |
url="https://github.com/rust-lang/mdBook/releases/download/v${MDBOOK_VERSION}/mdbook-v${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
mkdir -p "$RUNNER_TEMP/mdbook"
curl -sSfL "$url" | tar -xz -C "$RUNNER_TEMP/mdbook"
echo "$RUNNER_TEMP/mdbook" >> "$GITHUB_PATH"

- name: Build
run: mdbook build docs

# Pull requests only check that the book builds; nothing is published.
- if: github.event_name != 'pull_request'
uses: actions/configure-pages@v6

- if: github.event_name != 'pull_request'
uses: actions/upload-pages-artifact@v5
with:
path: docs/book

deploy:
name: deploy
if: github.event_name != 'pull_request'
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
# Let an in-progress deployment finish rather than cancelling it halfway.
concurrency:
group: pages
cancel-in-progress: false
steps:
- id: deployment
uses: actions/deploy-pages@v5
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
.idea/
.vscode/
*.swp
/docs/book
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- **A user guide**, published at
<https://smaranjit.github.io/firebase-token-toolkit/>. It walks through
setting up a Firebase project, every tab, profiles and the Users panel, and
lists the error messages the app can show with what each one means. The
screenshots come from a real demo project, and the README now opens with a
short recording of the main flow.

### Fixed

- `README.md` and `SECURITY.md` called the persistence checkbox "Remember
secrets"; its label is **remember API key & App ID**. They also left out that
the App Check debug token is gated by the same checkbox, and `SECURITY.md`
described a GitHub link in the footer that now lives in the About dialog.

## [0.1.6]

### Changed
Expand Down
19 changes: 19 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ resource compiler, and if `cargo-xwin` can't supply one the build still succeeds
prints a warning and produces an iconless binary. Official releases come from the
native Windows CI runner, so they always have the icon.

## Documentation

The user guide lives in `docs/` as an [mdBook](https://rust-lang.github.io/mdBook/)
and is published to GitHub Pages by `docs.yml` on every push to `main` that
touches it. Pull requests that change `docs/` get a build check. To preview:

```bash
mdbook serve docs --open
```

Use the mdBook version pinned in `.github/workflows/docs.yml`; newer minor
releases have broken older books before.

When a change alters what the UI shows (a label, a message, a new control),
update the page that quotes it. The guide quotes labels exactly, so
`grep -rn 'Old label' docs/src` finds what needs changing. Screenshots live in
`docs/src/images/` and are taken at 1280×800 against a throwaway demo
Firebase project; never take them against a project with real users.

## Changing the icon

`assets/icon.svg` is the source. The PNG/ICO/ICNS set is generated and committed so
Expand Down
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ A native desktop GUI for the Firebase auth tokens you need during development an

[![CI](https://github.com/smaranjit/firebase-token-toolkit/actions/workflows/ci.yml/badge.svg)](https://github.com/smaranjit/firebase-token-toolkit/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
[![Docs](https://img.shields.io/badge/docs-user%20guide-blue.svg)](https://smaranjit.github.io/firebase-token-toolkit/)

![Loading users, picking one, and generating an ID token](docs/src/images/quick-start.gif)

**[Read the user guide →](https://smaranjit.github.io/firebase-token-toolkit/)** It covers setup, every tab, profiles, and troubleshooting.

## Install

Expand Down Expand Up @@ -37,14 +42,14 @@ xattr -dr com.apple.quarantine "/Applications/Firebase Token Toolkit.app"
## Features

- **Multiple profiles** — switch between Firebase projects (dev/staging/prod, multiple clients, …) from a dropdown in the top bar. Each profile remembers its own service-account path, project ID, API key, App ID, and debug token. Switching a profile reloads the service account and clears the user list, OAuth cache, selected UID, and all tab outputs.
- **UID → Custom Token** — sign a Firebase custom token (RS256) using a service account, with optional custom claims.
- **UID → ID Token** — one-shot: sign a custom token, then exchange it via `signInWithCustomToken`.
- **Custom Token → ID Token** — paste a custom token and exchange it for an ID token.
- **UID -> Custom Token** — sign a Firebase custom token (RS256) using a service account, with optional custom claims.
- **UID -> ID Token** — one-shot: sign a custom token, then exchange it via `signInWithCustomToken`.
- **Custom -> ID Token** — paste a custom token and exchange it for an ID token.
- **User Custom Claims** — set persistent `customAttributes` on a user record via `accounts:update`. Loads the user's existing claims, edits them as JSON, validates the 1000-byte limit, and supports a "clear all" action. Future ID tokens automatically include the saved claims.
- **App Check Debug Token** — exchange a registered debug token via `firebaseappcheck.googleapis.com`.
- **App Check** — exchange a registered debug token via `firebaseappcheck.googleapis.com`.
- **Dynamic UID picker** — a left-side panel lists every user via `accounts:batchGet` (paginated up to 5,000) and lets you search by email, phone, or UID. Direct lookups fall through to `accounts:lookup` for users not present in the loaded page.
- Decoded JWT claims table for every token, with timestamp → ISO conversion and clipboard copy.
- Persists project ID, service-account path, and last-used tab between launches. API keys and App IDs are persisted **only if you opt in** — see [Security](#security).
- Persists project ID, service-account path, and last-used tab between launches. API keys, App IDs and App Check debug tokens are persisted **only if you opt in** — see [Security](#security).

## Configure

Expand All @@ -54,7 +59,7 @@ In the top bar:
2. **API key** → Firebase Console → Project Settings → General → Web API Key. Only needed for the ID-token and App Check tabs.
3. **App ID** → only needed for the App Check tab.

The status indicator on the right turns green once the service account is loaded and an API key is set.
The status indicator next to the service account turns green and reads **ready** once the service account is loaded and an API key is set. The [quick start](https://smaranjit.github.io/firebase-token-toolkit/quick-start.html) walks through it with screenshots.

## Build from source

Expand Down Expand Up @@ -84,7 +89,7 @@ To reproduce the packaged release artifacts, see [`scripts/`](https://github.com

This tool handles Firebase **service-account private keys** and mints signed tokens with them. Please read [SECURITY.md](https://github.com/smaranjit/firebase-token-toolkit/blob/main/SECURITY.md) before using it against anything that matters — it covers what is written to disk, what stays in memory, and how to report a vulnerability.

The short version: the service account is read from the path you pick and never copied; OAuth access tokens live in memory only; API keys and App IDs are written to disk only when you tick **Remember secrets**.
The short version: the service account is read from the path you pick and never copied; OAuth access tokens live in memory only; API keys, App IDs and App Check debug tokens are written to disk only when you tick **remember API key & App ID**.

## Contributing

Expand Down
5 changes: 4 additions & 1 deletion README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ IF NOTHING OPENS

MORE

Full documentation, changelog, security notes and issue tracker:
User guide, with screenshots of every tab and a troubleshooting section:
https://smaranjit.github.io/firebase-token-toolkit/

Source, changelog, security notes and issue tracker:
https://github.com/smaranjit/firebase-token-toolkit

The About dialog, reached from the footer, links the changelog and
Expand Down
11 changes: 6 additions & 5 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ Persisted for every profile:
- **Service-account path** — the filesystem path only. The key file's contents are read
on demand and never copied into the config.
- Project ID, and the last-used tab.
- Window size and position.

Persisted **only when "Remember secrets" is enabled**:
Persisted **only when "remember API key & App ID" is enabled**:

- Web API key, App ID, and App Check debug token.

These are stored in **plaintext**. There is no OS keychain integration — the file is
protected by nothing but its filesystem permissions. If you would not paste the value
into a plaintext file, leave "Remember secrets" off. Turning it off clears those fields
into a plaintext file, leave "remember API key & App ID" off. Turning it off clears those fields
for *all* profiles on the next save (`clear_secrets_all` in `src/config.rs`).

**Never persisted:** the service-account private key, OAuth access tokens, and any
Expand Down Expand Up @@ -62,9 +63,9 @@ All requests go to Google endpoints over TLS (`rustls` — no OpenSSL):
There is **no telemetry, analytics, or update check**. The application makes no
network request you did not initiate.

The one thing that leaves the app besides the calls above is the **GitHub** link
in the footer, which hands the repository URL to your system browser when you
click it. Nothing is sent with it.
The only other thing that leaves the app is a link you click in the **About**
dialog (Source, Contributors, Report an issue, Changelog, Security notes), which
hands that URL to your system browser. Nothing is sent with it.

## Things worth knowing

Expand Down
15 changes: 15 additions & 0 deletions docs/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[book]
title = "Firebase Token Toolkit"
description = "User guide for Firebase Token Toolkit, a desktop app for minting and inspecting Firebase auth tokens."
authors = ["Smaranjit Maiti"]
language = "en"
src = "src"

[output.html]
site-url = "/firebase-token-toolkit/"
git-repository-url = "https://github.com/smaranjit/firebase-token-toolkit"
edit-url-template = "https://github.com/smaranjit/firebase-token-toolkit/edit/main/docs/{path}"
no-section-label = true

[output.html.fold]
enable = false
29 changes: 29 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Summary

[Introduction](introduction.md)

# Getting started

- [Installation](installation.md)
- [Preparing your Firebase project](firebase-setup.md)
- [Quick start](quick-start.md)

# Using the app

- [The top bar](configuration.md)
- [Profiles](profiles.md)
- [The Users panel](guide/users-panel.md)
- [UID -> Custom Token](guide/uid-to-custom-token.md)
- [UID -> ID Token](guide/uid-to-id-token.md)
- [Custom -> ID Token](guide/custom-to-id-token.md)
- [User Custom Claims](guide/custom-claims.md)
- [App Check](guide/app-check.md)
- [Reading the results](guide/reading-results.md)

# Reference

- [Settings and storage](reference/settings-storage.md)
- [Google endpoints](reference/endpoints.md)
- [Troubleshooting](troubleshooting.md)
- [Security](security.md)
- [Building and contributing](contributing.md)
59 changes: 59 additions & 0 deletions docs/src/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# The top bar

Everything the tabs need comes from the top bar. Its values belong to the
active [profile](profiles.md), so switching profiles swaps them all at once.

![The top bar with a service account loaded and the indicator reading ready](images/top-bar-ready.png)

## Service account

**Browse…** opens a file chooser for the service-account JSON key. When the key
loads, a green *Service account loaded* message appears, and if **Project ID**
is empty it is filled in from the key.

**Clear** unloads the key and clears the selected user. It also clears
**Project ID**, but only if the key filled that value in and you have not
edited it since.

The app stores the file's path, not its contents, and reads the key again on
every launch. If the file has moved, the profile starts with no service
account loaded.

## Status indicator

The indicator to the right of the service account shows what the app can do
right now:

| Indicator | Meaning | Tabs available |
|---|---|---|
| **not configured** (red) | No service account loaded | *Custom -> ID Token* and *App Check* only, given an API key |
| **SA only** (yellow) | Service account loaded, no API key | *UID -> Custom Token*, *User Custom Claims*, the Users panel |
| **ready** (green) | Service account and API key | All tabs (*App Check* also needs an App ID) |

## Project ID

The Firebase project ID, for example `fir-token-toolkit-demo`. The Users panel,
User Custom Claims and App Check use it to build their requests. It normally
comes from the key file, but you can edit it.

## API key

The project's Web API key. The ID-token tabs and App Check send it to Google
with each request. The field is masked.

## App ID

The web app's App ID, used only by the App Check tab.

## remember API key & App ID

Off by default. When ticked, the API key, App ID and App Check debug token are
saved to disk in plaintext for **every** profile. When unticked, they are kept
in memory only and cleared from every profile the next time the app saves. See
[Settings and storage](reference/settings-storage.md).

## Selected UID

Once you pick a user in the [Users panel](guide/users-panel.md), a **Selected
UID** row shows their UID and, in grey, their email or phone and display name.
The UID-based tabs act on this user.
44 changes: 44 additions & 0 deletions docs/src/contributing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Building and contributing

## Build from source

You need Rust 1.90 or newer.

```bash
git clone https://github.com/smaranjit/firebase-token-toolkit
cd firebase-token-toolkit
cargo build --release
# the binary is target/release/firebase-token-toolkit
```

Linux also needs the windowing and clipboard development headers:

```bash
sudo apt install -y \
libxkbcommon-dev libxkbcommon-x11-dev libwayland-dev libgl1-mesa-dev \
libx11-dev libxrandr-dev libxi-dev libxcursor-dev \
libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev pkg-config
```

Windows needs the MSVC toolchain from Visual Studio Build Tools, and macOS
needs the Xcode command line tools. TLS goes through `rustls`, so no platform
needs OpenSSL.

## Contributing

Issues and pull requests are welcome.
[`CONTRIBUTING.md`](https://github.com/smaranjit/firebase-token-toolkit/blob/main/CONTRIBUTING.md)
covers the checks CI runs, the project layout, building release archives and
cutting a release.

## Editing this guide

The guide is an [mdBook](https://rust-lang.github.io/mdBook/) in the `docs/`
folder of the repository. To preview changes locally:

```bash
mdbook serve docs --open
```

Every page has an edit icon in the top-right corner that opens it on GitHub.
Changes merged to `main` are published automatically.
Loading
Loading