Skip to content

fix(auth): allow dev-impersonation in production builds via runtime o… - #166

Merged
cyberantonz merged 2 commits into
constructorfabric:mainfrom
cyberantonz:feat/backend-for-frontend
Jun 16, 2026
Merged

fix(auth): allow dev-impersonation in production builds via runtime o…#166
cyberantonz merged 2 commits into
constructorfabric:mainfrom
cyberantonz:feat/backend-for-frontend

Conversation

@cyberantonz

@cyberantonz cyberantonz commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

…pt-in

Dev impersonation was gated three places on import.meta.env.DEV (Vite's dev-server flag) — oidc-manager.ts (auth bypass when no OIDC config), use-viewer.ts (isDevImpersonating), fetch-with-auth.ts (devBearer). Production bundles set DEV=false, so the published ghcr image silently fell into status=unauthorized,missing_oidc_config when stood up in the docker-compose dev stack: SPA halts before any /api call, no errors, black screen.

Replaces the build-mode gate with a runtime opt-in:

  • src/auth/types.ts adds window.DEV_CONFIG?: { devUserEmail?: string }.
  • src/auth/dev-config.ts (new) reads it.
  • src/auth/use-viewer.ts resolves the dev email from runtime first, falling back to import.meta.env.VITE_DEV_USER_EMAIL only when in Vite dev. isDevImpersonating() drops its DEV gate.
  • src/auth/oidc-manager.ts bypasses auth when no OIDC config AND (DEV OR a runtime dev email is present).
  • src/api/fetch-with-auth.ts drops the DEV gate on devBearer().

docker-entrypoint.sh validates a new DEV_USER_EMAIL env var (same unsafe-char check as OIDC_*), refuses to honor it when OIDC_ISSUER / OIDC_CLIENT_ID are also set (mutually exclusive), and writes window.DEV_CONFIG = { devUserEmail: "..." } into oidc-config.js when only DEV_USER_EMAIL is set.

Safety: a production deploy that doesn't set DEV_USER_EMAIL still fails closed exactly as before. The dev path is strictly opt-in via the env var, set only in insight's docker-compose.yml for the insight-front-ghcr service.

Summary by CodeRabbit

  • New Features

    • Added runtime dev user impersonation that can inject a dev identity when no OIDC configuration is available.
    • Validates the provided dev email and only enables impersonation when the active viewer source is “dev” or “override”.
  • Improvements

    • Updated auth flow to bypass OIDC only when runtime dev identity is present (or in dev mode), otherwise requiring OIDC.
    • Improved handling of the runtime OIDC config file by clearing it first and writing the correct runtime config (OIDC, dev impersonation, or empty).
    • Refreshed startup messaging to reflect which config branch was written.

…pt-in

Dev impersonation was gated three places on import.meta.env.DEV (Vite's
dev-server flag) — oidc-manager.ts (auth bypass when no OIDC config),
use-viewer.ts (isDevImpersonating), fetch-with-auth.ts (devBearer).
Production bundles set DEV=false, so the published ghcr image silently
fell into status=unauthorized,missing_oidc_config when stood up in the
docker-compose dev stack: SPA halts before any /api call, no errors,
black screen.

Replaces the build-mode gate with a runtime opt-in:

* src/auth/types.ts adds window.__DEV_CONFIG__?: { devUserEmail?: string }.
* src/auth/dev-config.ts (new) reads it.
* src/auth/use-viewer.ts resolves the dev email from runtime first,
  falling back to import.meta.env.VITE_DEV_USER_EMAIL only when in
  Vite dev. isDevImpersonating() drops its DEV gate.
* src/auth/oidc-manager.ts bypasses auth when no OIDC config AND
  (DEV OR a runtime dev email is present).
* src/api/fetch-with-auth.ts drops the DEV gate on devBearer().

docker-entrypoint.sh validates a new DEV_USER_EMAIL env var (same
unsafe-char check as OIDC_*), refuses to honor it when OIDC_ISSUER /
OIDC_CLIENT_ID are also set (mutually exclusive), and writes
window.__DEV_CONFIG__ = { devUserEmail: "..." } into oidc-config.js
when only DEV_USER_EMAIL is set.

Safety: a production deploy that doesn't set DEV_USER_EMAIL still
fails closed exactly as before. The dev path is strictly opt-in via
the env var, set only in insight's docker-compose.yml for the
insight-front-ghcr service.

Signed-off-by: Anton Zelenov <antonz@constructor.tech>
@cyberantonz
cyberantonz requested a review from a team as a code owner June 16, 2026 11:02
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ae6cbf91-60e3-45e3-b64f-58090af27893

📥 Commits

Reviewing files that changed from the base of the PR and between 58bbb2a and f20ee62.

📒 Files selected for processing (3)
  • docker-entrypoint.sh
  • src/api/fetch-with-auth.ts
  • src/auth/use-viewer.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • docker-entrypoint.sh

📝 Walkthrough

Walkthrough

Adds a runtime dev impersonation mode controlled by DEV_USER_EMAIL. The container entrypoint validates the variable and writes window.__DEV_CONFIG__ into oidc-config.js. A new readDevUserEmail() utility reads and normalizes that value. The auth layer uses it to bypass OIDC and resolve viewer identity without requiring a Vite dev build.

Changes

Runtime Dev Impersonation via DEV_USER_EMAIL

Layer / File(s) Summary
Container entrypoint: DEV_USER_EMAIL validation and config emission
docker-entrypoint.sh
Validates DEV_USER_EMAIL (rejects whitespace/control characters, rejects co-presence with OIDC vars), always truncates oidc-config.js up-front, and writes window.__DEV_CONFIG__ for the dev branch, window.__OIDC_CONFIG__ for OIDC, or leaves the file empty.
Window.__DEV_CONFIG__ type and readDevUserEmail utility
src/auth/types.ts, src/auth/dev-config.ts
Extends the global Window type with an optional __DEV_CONFIG__ shape, and adds readDevUserEmail() which reads, type-checks, trims, and normalizes the runtime email to null when absent or blank.
Auth bypass and viewer identity using runtime dev email
src/auth/oidc-manager.ts, src/auth/use-viewer.ts, src/api/fetch-with-auth.ts
oidc-manager expands the OIDC bypass condition to include a runtime dev email. use-viewer refactors dev-email resolution into resolveDevEmail(), preferring the runtime value and restricting build-time fallback to Vite dev builds; exports getDevBearerEmail() and updates isDevImpersonating() to use the resolved source. devBearer() drops the import.meta.env.DEV guard, relying on getDevBearerEmail() returning null in production without impersonation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 A rabbit hops in with a dev disguise,
No build flag needed — just set the email, wise!
The entrypoint writes it, the config reads clean,
Auth skips its dance for this impersonation scheme.
In prod, stay silent; in dev, hop right through —
DEV_USER_EMAIL unlocks the view! 🔑

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: enabling dev-impersonation in production builds via a runtime mechanism (the truncated text indicates 'runtime configuration'), which is well-supported by the summary showing replacement of build-time gates with runtime configuration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docker-entrypoint.sh`:
- Around line 55-59: The runtime configuration documentation needs to be updated
to reflect the current implementation that supports both __OIDC_CONFIG__ and
__DEV_CONFIG__ modes. Update the README or relevant documentation to include:
documentation for the __DEV_CONFIG__ variable and DEV_USER_EMAIL parameter,
clarification that __OIDC_CONFIG__ and __DEV_CONFIG__ are mutually exclusive
options, and the production-bundle dev-stack path for development. Remove
references to only the old Vite-dev-only bypass approach to match the current
behavior described in the docker-entrypoint.sh comment block.
- Line 76: The echo statement on the dev config line includes the DEV_USER_EMAIL
variable, which is PII and should not appear in container logs. Remove the
`devUserEmail=$DEV_USER_EMAIL` portion from the echo message while preserving
the informational parts that indicate dev config was written and auth was
bypassed. This maintains the startup signal without retaining user identifiers
in logs.

In `@src/api/fetch-with-auth.ts`:
- Around line 5-10: The devBearer() function currently uses getViewerEmail()
which can return OIDC or override identities, not just legitimate dev
identities, creating a security issue where unsigned bearer tokens could be sent
outside the intended opt-in path. Add a source-aware helper in
src/auth/use-viewer.ts that distinguishes actual dev identities from generic
viewer emails, then replace the devBearer() function logic (lines 5-10 in
src/api/fetch-with-auth.ts) to gate the unsigned JWT generation on this new
source-aware check instead of just checking getViewerEmail(). Apply the same
source-aware gating to the other affected location at lines 27-29 in
src/api/fetch-with-auth.ts where the token ?? devBearer() expression is used.

In `@src/auth/use-viewer.ts`:
- Around line 66-71: The isDevImpersonating() function currently returns true
whenever mocks are enabled or a dev email is configured, but it should only
return true when the active viewer source is actually from dev/mocks. Since
resolve() gives OIDC and overrides precedence over dev sources, the current
logic can incorrectly show impersonation UI even when the active viewer identity
source is not dev. Modify the isDevImpersonating() function to check that the
actual source of the current viewer identity is from dev/mocks before returning
true, rather than just checking if those options exist.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 425ae7a4-90d6-4083-aa76-d09692fa0321

📥 Commits

Reviewing files that changed from the base of the PR and between bddede7 and 58bbb2a.

📒 Files selected for processing (6)
  • docker-entrypoint.sh
  • src/api/fetch-with-auth.ts
  • src/auth/dev-config.ts
  • src/auth/oidc-manager.ts
  • src/auth/types.ts
  • src/auth/use-viewer.ts

Comment thread docker-entrypoint.sh
Comment thread docker-entrypoint.sh Outdated
Comment thread src/api/fetch-with-auth.ts Outdated
Comment thread src/auth/use-viewer.ts Outdated
…urce

Addresses CodeRabbit review feedback on PR #166.

devBearer() called getViewerEmail(), which can resolve to an OIDC
user's email when OIDC is mid-bootstrap (authStore.token still null,
but resolve() falls through MOCKS/dev branches). That would mint an
unsigned JWT bearing the real user's identity — leak path in any
Vite-dev session with both VITE_OIDC_* and VITE_DEV_USER_EMAIL set.
Production builds are still safe (entrypoint refuses OIDC+DEV combo)
but the source-aware gate is the correct fix at the source level.

Adds getDevBearerEmail() in use-viewer.ts that returns the email
only when the active viewer source is dev-style ('dev' for
runtime/build-time dev email or MOCKS; 'override' for sessionStorage
impersonation) — never for 'oidc' or 'none'. devBearer() switches
to it.

isDevImpersonating() previously returned true whenever a dev email
was configured, even if OIDC was the active source — could surface
the impersonation banner / hint over a real OIDC session. Now reads
the active source from resolve().

docker-entrypoint.sh stops echoing DEV_USER_EMAIL on startup —
deployers pointing it at a real mailbox would have leaked PII into
container logs.

Skipped: CodeRabbit's docs-update suggestion (no separate README in
scope; the inline comment block in the entrypoint already describes
both __OIDC_CONFIG__ and __DEV_CONFIG__ modes).

Signed-off-by: Anton Zelenov <antonz@constructor.tech>
@cyberantonz
cyberantonz merged commit 31b9825 into constructorfabric:main Jun 16, 2026
2 checks passed
@cyberantonz
cyberantonz deleted the feat/backend-for-frontend branch July 28, 2026 07:57
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