Skip to content

Fix/auto generate jwt secret - #94

Merged
diegosouzapw merged 3 commits into
diegosouzapw:mainfrom
StealthIQ:fix/auto-generate-jwt-secret
Feb 21, 2026
Merged

diegosouzapw merged 3 commits into
diegosouzapw:mainfrom
StealthIQ:fix/auto-generate-jwt-secret

Conversation

@StealthIQ

Copy link
Copy Markdown
Contributor

Summary

  • Fixes auth_error: JWT verification failed #92 Running the app via CLI without a JWT_SECRET used to trigger a fatal JWT verification failure. This PR fixes that issue by generating a fallback secret and cleans up the login flow so new users aren't hit with authentication errors right out of the gate.

Changes

JWT Secret Auto-Generation

  • Added ensureJwtSecret() to instrumentation.ts. It generates a random 64-character secret at startup if you don't provide one.
  • Marked JWT_SECRET as optional in secretsValidator.ts.
  • Dropped the fatal error log for missing secrets in proxy.ts.

Login Flow

  • Reworked the login page into a simpler two-column layout.
  • The page now handles three distinct states. It pushes new users to the onboarding wizard, prompts users without passwords to set one, and gives existing users a standard sign-in form.
  • Added basic loading spinners and UI transitions.

Settings & UI Tweaks

  • Added setupComplete to the settings validation schema so state persists correctly.
  • Added support for the ?tab= query parameter so you can link directly to specific tabs (e.g., /dashboard/settings?tab=security).
  • Swapped the 404 page theme color from purple to coral red to match the rest of the app.

Files Changed

  • src/instrumentation.ts: Added auto-generation logic.
  • src/proxy.ts: Removed fatal error.
  • src/shared/utils/secretsValidator.ts: Updated validation rules.
  • src/shared/validation/schemas.ts: Added setupComplete.
  • src/app/login/page.tsx: Rewrote login UX.
  • src/app/(dashboard)/dashboard/settings/page.tsx: Added query param support.
  • src/app/not-found.tsx: Fixed theme colors.

Testing
Tested locally. Verified the login flow works on a fresh CLI install without a secret, and that existing setups with secrets do not break. Checked all three login states (onboarding, password setup, standard).

Before / After

  • Before: App crashed with a middleware auth_error if JWT_SECRET was missing.
  • After: The app handles missing secrets gracefully and routes users to the proper setup step.

Screenshots

  • Issues
image image - Fix 1. Redirects to onboarding page 2. If user in /login route image 2.1. If onboarding over still password not set -> Redirected back to seeting?tab=password image
  1. 404 Page
image

Before: Login failed without JWT_SECRET

Middleware auth_error: JWT verification failed: signature verification failed

After: Auto-generated secret + contextual login

Users are guided through setup instead of hitting authentication errors.

- Add ensureJwtSecret() in instrumentation.ts to generate random 64-char secret
- Mark JWT_SECRET as non-required in secretsValidator
- Remove fatal error log for missing JWT_SECRET in proxy.ts
Fixes login failure when running via CLI without JWT_SECRET env var.
- Add setupComplete to settings validation schema for proper persistence
- Support ?tab= query param in settings page for direct tab navigation
- Redesign login page with professional two-column layout
- Add context-aware states for onboarding/password setup flows
- Smooth animations and refined visual hierarchy
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @StealthIQ, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the application's initial setup and user experience by addressing critical authentication issues and streamlining the onboarding process. It introduces automatic JWT secret generation to ensure the application starts gracefully even without explicit configuration, and completely revamps the login page to provide contextual guidance to users based on their setup status. Additionally, it enhances UI navigation and consistency across various parts of the application.

Highlights

  • JWT Secret Auto-Generation: The application now automatically generates a random 64-character JWT secret at startup if the JWT_SECRET environment variable is not provided, preventing previous fatal authentication errors.
  • Reworked Login Flow: The login page has been completely redesigned to intelligently handle three distinct states: guiding new users to an onboarding wizard, prompting users without a password to set one, and presenting a standard sign-in form for existing users.
  • Enhanced Settings Navigation: The dashboard settings page now supports direct linking to specific tabs using a ?tab= query parameter, improving navigation and shareability.
  • Configuration Robustness: The JWT_SECRET is now marked as optional in the secrets validator, aligning with its new auto-generation capability, and a setupComplete flag was added to the settings schema for better state persistence.
  • UI Consistency: The 404 error page's theme colors were updated to match the application's primary color scheme, ensuring a more cohesive user experience.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/app/(dashboard)/dashboard/settings/page.tsx
    • Imported useSearchParams for URL query parameter access.
    • Implemented logic to read the tab query parameter and set the active tab accordingly.
    • Updated tab click handler to manage user-selected tab state.
  • src/app/login/page.tsx
    • Removed Card component import.
    • Added setupComplete and mounted state variables to manage UI transitions and setup status.
    • Modified useEffect hook to check for setupComplete status alongside hasPassword.
    • Updated loading state to account for both hasPassword and setupComplete checks.
    • Introduced conditional rendering to display different UI based on whether setup is complete, a password is set, or a standard login is required.
    • Redesigned the login layout to a two-column structure for the standard sign-in form, incorporating new styling and UI elements.
  • src/app/not-found.tsx
    • Removed internal comments.
    • Updated CSS classes to change the 404 page's background, text, and button colors to align with the application's primary theme.
  • src/instrumentation.ts
    • Imported the crypto module.
    • Added ensureJwtSecret() function to generate a random 64-character base64 encoded string for process.env.JWT_SECRET if it's not already set.
    • Called ensureJwtSecret() within the register function to ensure the secret is available at startup.
  • src/proxy.ts
    • Removed the console.error log that previously warned about a missing JWT_SECRET.
    • Modified the SECRET variable initialization to use an empty string as a fallback if process.env.JWT_SECRET is undefined, preventing potential errors during TextEncoder conversion.
  • src/shared/utils/secretsValidator.ts
    • Changed the required property for JWT_SECRET from true to false.
    • Updated the description for JWT_SECRET to indicate that it is auto-generated if not explicitly set.
  • src/shared/validation/schemas.ts
    • Added an optional setupComplete boolean field to the updateSettingsSchema.
Activity
  • The author tested the changes locally to ensure the login flow functions correctly on a fresh CLI installation without a JWT_SECRET.
  • Verification was performed to confirm that existing setups with pre-configured secrets were not adversely affected.
  • All three new login states (onboarding, password setup, and standard sign-in) were checked and validated.
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 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 counter productive. 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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@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 aims to simplify initial setup by auto-generating the JWT_SECRET and refining the login flow. However, a critical vulnerability has been identified in src/proxy.ts related to insecure JWT secret handling, which could lead to authentication bypass. Additionally, a high-severity privilege escalation flaw exists in src/shared/validation/schemas.ts, allowing authenticated users to reset the application's setup state and change the admin password. Beyond these security concerns, there are also issues with the persistence and propagation of the auto-generated secret, and the synchronization of settings page tabs with the URL.

Comment thread src/proxy.ts
}

const SECRET = new TextEncoder().encode(process.env.JWT_SECRET);
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET || "");

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.

security-critical critical

The use of an empty string ("") as a fallback for the JWT_SECRET in src/proxy.ts is a critical vulnerability. If process.env.JWT_SECRET is missing or fails to propagate, the SECRET constant will be initialized with an empty value. This allows attackers to bypass authentication by forging tokens signed with an empty key, violating the "Fail Securely" principle. The secret should be loaded and validated within the request lifecycle, not at the module level. Initialize the secret inside the proxy function and add a check to ensure it is not empty, failing the request if it is.

logRetentionDays: z.number().int().min(1).max(365).optional(),
cloudUrl: z.string().max(500).optional(),
baseUrl: z.string().max(500).optional(),
setupComplete: z.boolean().optional(),

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.

security-high high

Adding setupComplete to the updateSettingsSchema allows any authenticated user to modify this flag via the /api/settings endpoint. An attacker could set setupComplete: false, which reverts the application to its initial setup state. This re-enables the onboarding wizard, which allows setting a new admin password without requiring the current one. This could lead to a full account takeover by any authenticated user.

Suggested change
setupComplete: z.boolean().optional(),
// setupComplete: z.boolean().optional(),

Comment thread src/instrumentation.ts
Comment on lines +14 to +18
if (!process.env.JWT_SECRET || process.env.JWT_SECRET.trim() === "") {
const generated = crypto.randomBytes(48).toString("base64");
process.env.JWT_SECRET = generated;
console.log("[STARTUP] JWT_SECRET auto-generated (random 64-char secret)");
}

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.

high

The auto-generated secret is stored in process.env at runtime, which presents two major issues: 1. Persistence: The secret is lost on every server restart, invalidating all active user sessions and forcing logouts. 2. Propagation: In Next.js, environment variables modified in the Node.js runtime of instrumentation.ts do not reliably propagate to the Middleware (which often runs in the Edge runtime or a separate process). This means the Middleware might still see an undefined secret, leading to the authentication errors this PR intends to fix. Consider using a persistent storage mechanism or a stable machine-specific seed for zero-config setups.

Comment thread src/app/(dashboard)/dashboard/settings/page.tsx
@diegosouzapw
diegosouzapw merged commit 567d0c6 into diegosouzapw:main Feb 21, 2026
diegosouzapw pushed a commit that referenced this pull request Mar 7, 2026
* fix: auto-generate JWT_SECRET at startup if not provided
- Add ensureJwtSecret() in instrumentation.ts to generate random 64-char secret
- Mark JWT_SECRET as non-required in secretsValidator
- Remove fatal error log for missing JWT_SECRET in proxy.ts
Fixes login failure when running via CLI without JWT_SECRET env var.

* feat: improve auth flow and login page UX
- Add setupComplete to settings validation schema for proper persistence
- Support ?tab= query param in settings page for direct tab navigation
- Redesign login page with professional two-column layout
- Add context-aware states for onboarding/password setup flows
- Smooth animations and refined visual hierarchy

* fix: 404 page to use primary color theme (coral red) instead of purple
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.

auth_error: JWT verification failed

2 participants