Skip to content

feat(middleware): user identity verification pipeline (RFC) - #48

Merged
syucream merged 1 commit into
mainfrom
feat/user-identity-verification
Jul 22, 2026
Merged

feat(middleware): user identity verification pipeline (RFC)#48
syucream merged 1 commit into
mainfrom
feat/user-identity-verification

Conversation

@syucream

@syucream syucream commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds five middlewares that let a Cloud Run / IAP-fronted deployment attribute proxy calls to the actual human running the CLI — cryptographically, without trusting client-side claims.

New middlewares

Server-side (ingress):

  • oauth-verify — verifies Authorization: Bearer via Google tokeninfo; pins iss / aud allowlist / email_verified
  • impersonator-verify — verifies a side header (X-Impersonator-Id-Token) as the human user's own Google id_token; only honored when the primary bearer is a pre-registered trusted SA (spoof prevention)
  • caller-authz — generic external-authz gate resolving the effective identity to a group list via a configurable HTTP endpoint

Client-side (egress):

  • impersonator-token — mints the current user's Google id_token via ADC refresh-token grant and attaches it as X-Impersonator-Id-Token

Also included

Test plan

  • bun run typecheck — 0 errors
  • bun test — 971 pass / 0 fail (baseline 914 + 57 new)
  • bun run lint — exit 0
  • bun run build — produces working binary

Status

Draft / RFC — posted to solicit review before finalizing.

🤖 Generated with Claude Code

@syucream
syucream force-pushed the feat/user-identity-verification branch 3 times, most recently from d501382 to 985a06f Compare July 22, 2026 05:39
Bumps to 2.4.0. Middlewares that have shipped in prior 2.x releases are
reshaped here — the option surface, some option names, and the file
layout change — but the middleware system itself is still stabilizing,
so this is not called out as a semver-major.

Three middlewares that let any deployment authenticate callers via
signed id_tokens, without hardcoding Google as the sole issuer:

  Server (verifies inbound):
    - oauth-verify        — verifies the incoming Authorization: Bearer
                            through a pluggable `IdTokenVerifier`
                            interface. `GoogleTokeninfoVerifier` ships
                            as the reference implementation; other
                            issuers plug in their own verifier via
                            `options.verifier`.
    - impersonator-verify — verifies a side-channel id_token
                            (`X-Impersonator-Id-Token` by default),
                            only when the bearer principal is in an
                            explicit trusted list.

  Client (rewrites outbound):
    - impersonator-token  — attaches a user-owned id_token as a side
                            header. Token sources are pluggable:
                            `env` (default) / `static` / `adc`
                            (Google gcloud ADC, kept behind an
                            explicit selector).

  `src/middleware/auth/types.ts` — `IdTokenVerifier` interface and the
  neutral `VerifiedClaim` shape both middlewares consume.

  `src/middleware/auth/google-tokeninfo.ts` — Google's tokeninfo
  reference implementation of `IdTokenVerifier`. Kept in its own file
  so non-Google users never accidentally import it.

  `src/middleware/builtin/impersonator-token/adc-user-token-source.ts`
  — Google-specific ADC user token source, separated from the generic
  `UserTokenSource` interface so it isn't the silent default.

  - Cache expiry is now capped at the token's own `exp` — expired
    tokens can no longer replay past their rated lifetime just because
    the local cache TTL was longer.
  - Rejection responses no longer echo the received `aud` value to the
    caller (small info-disclosure hardening).
  - The ADC token source no longer memoizes an initial read failure —
    users who start the CLI before running `application-default login`
    can now recover without restarting the process.
  - Dockerfile build stage switched to the debian-based `oven/bun`
    image so the runtime distroless/debian12 image can actually exec
    the compiled binary (was cross-libc before).

Trimmed to the fields that materially affect a deployment; tunable
knobs (timeouts, cache TTLs, custom endpoints) stay programmatic-only
for test injection. Renamed `trustedServiceAccounts` →
`trustedPrincipals` (both the option name and the corresponding
`--oauth-verify-trusted-principals` / `N8N_OAUTH_VERIFY_TRUSTED_PRINCIPALS`
CLI and env surface) so the vocabulary doesn't presume Google service
accounts.

`bun run typecheck` clean; `bun test tests/middleware/` passes 170/170;
`bun run lint` exit 0.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@syucream
syucream force-pushed the feat/user-identity-verification branch from 985a06f to d5113a5 Compare July 22, 2026 05:42
@syucream
syucream marked this pull request as ready for review July 22, 2026 05:43
@syucream
syucream merged commit f3f879d into main Jul 22, 2026
4 checks passed
@syucream
syucream deleted the feat/user-identity-verification branch July 22, 2026 05:43
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.

1 participant