Skip to content

feat(auth): add native Google and GitHub OAuth login for Dashboard - #15153

Open
trinitynexusai wants to merge 2 commits into
diegosouzapw:release/v3.8.52from
abrantess:feature/social-oauth-google-github
Open

trinitynexusai wants to merge 2 commits into
diegosouzapw:release/v3.8.52from
abrantess:feature/social-oauth-google-github

Conversation

@trinitynexusai

Copy link
Copy Markdown

Summary

Adds native Google OAuth 2.0 ("Continue with Google") and GitHub OAuth ("Continue with GitHub") authentication support to the OmniRoute management dashboard.

Highlights:

  • Zero New Dependencies: Utilizes native Web standards (fetch, crypto, URL) and the existing jose library already bundled in OmniRoute.
  • Strict Security & CSRF Defense: Uses cryptographically secure random state nonces stored in short-lived HTTP-only cookies (maxAge: 600) and validated via timingSafeCompare (constant-time equality) to defeat timing attacks (GHSA-7434-6q4c-33fh).
  • Verified Identity Enforcement: Requires email_verified: true for Google accounts and checks for verified primary emails for GitHub accounts before authorizing session issuance.
  • Configurable Access Governance: Supports AUTH_ALLOWED_EMAILS (comma-separated email list, domain wildcards like *@company.com, or GitHub usernames). Defaults to permissive if unconfigured (matching self-hosted single-admin expectations).
  • Session Minting Parity: Mints the exact same 30-day auth_token JWT carrying authenticated: true signed with JWT_SECRET through verifyDashboardSessionToken / createDashboardSessionJwt.
  • UI/UX Polish: Adds responsive, accessible Google and GitHub branded SVG buttons to src/app/login/page.tsx with localized strings (en, pt-BR) and an optional separator (or / ou), fully preserving password login and enterprise OIDC coexistence.
  • Opt-in Password Disabling: Supports AUTH_DISABLE_PASSWORD_LOGIN=true when operators wish to enforce SSO-only access.

Related Issues


Validation

  • Change type: UI / routing / DB / i18n
  • Focused tests and category gates from the golden path
  • Production-code changes include new automated tests in this PR
  • Verified against #13298 dashboard session verifier source guard: zero regressions

Tests Added Or Updated

  • tests/unit/social-oauth.test.ts:
    • timingSafeCompare constant-time string comparison
    • isEmailAllowed allowlist parsing, wildcard matching, case-insensitivity
    • getGoogleOAuthConfig and getGitHubOAuthConfig environment and settings resolution
    • getRequestOrigin host and forwarded proto derivation
    • createDashboardSessionJwt minting and validation through verifyDashboardSessionToken
  • tests/unit/social-oauth-routes.test.ts:
    • GET /api/auth/google/login: Configuration guard, authorization URL construction, and state cookie setting
    • GET /api/auth/google/callback: Code exchange, state mismatch defense, email allowlist blocking, and session issuance
    • GET /api/auth/github/login: Redirect to GitHub authorize and state cookie generation
    • GET /api/auth/github/callback: Token exchange, verified email resolution, allowlist filtering, and session cookie minting
  • tests/unit/dashboard-session-verifier-source-guard.test.ts: Re-validated 8/8 tests passing.

Coverage Notes

  • All new helper logic in src/lib/auth/socialOAuth.ts is 100% covered by unit tests.
  • All new API routes under src/app/api/auth/google/ and src/app/api/auth/github/ are covered with simulated provider responses and cookie capture test seams (*Internals.getCookieStore).
  • Zero modifications to core proxy routing or inference paths.

Reviewer Notes

  • Environment Variables Supported:
    • AUTH_GOOGLE_CLIENT_ID / GOOGLE_CLIENT_ID
    • AUTH_GOOGLE_CLIENT_SECRET / GOOGLE_CLIENT_SECRET
    • AUTH_GITHUB_CLIENT_ID / GITHUB_CLIENT_ID
    • AUTH_GITHUB_CLIENT_SECRET / GITHUB_CLIENT_SECRET
    • AUTH_ALLOWED_EMAILS (optional comma-separated list of allowed emails or wildcard domains)
    • AUTH_DISABLE_PASSWORD_LOGIN (optional boolean, true disables password login form)
  • Settings can also be populated dynamically via SQLite settings table (googleClientId, googleClientSecret, githubClientId, githubClientSecret), where secrets are automatically encrypted via STORAGE_ENCRYPTION_KEY.

…efault

- classify /api/auth/google/ and /api/auth/github/ as public routes (they were MANAGEMENT, so
  requireLogin answered 401 before the login handler ran) + classifyRoute regression test
- deny-by-default allowlist: an empty list or a bare "*" admits nobody and a provider stays
  disabled until AUTH_ALLOWED_EMAILS is non-empty; drop the generic GOOGLE_/GITHUB_CLIENT_ID
  fallbacks; GitHub usernames only match bare username entries
- GitHub: no fallback to the unverified public profile e-mail (fail closed)
- redirect_uri/redirect origin use Host only (no X-Forwarded-Host); redirect paths from settings
  must be same-origin absolute paths; OAuth state comes from crypto.randomUUID() only
- login routes answer through errorResponse(); callbacks split into helpers, no `any`
- restore the oidcRedirectPath default dropped by the PR; remove PULL_REQUEST.md from the root
- settingsSchemas: add the social-login keys; GET/PATCH /api/settings never return the client
  secrets; the new keys are password-gated security settings
- i18n: login keys in all locales, error strings through t()
- document AUTH_GOOGLE_*, AUTH_GITHUB_*, AUTH_ALLOWED_EMAILS, AUTH_DISABLE_PASSWORD_LOGIN

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant