feat: Add Google/GitHub social login providers for Demo environment (GRO-531) #249
Reference in New Issue
Block a user
Delete Branch "fix/gro-531-social-login"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
apps/api/src/lib/auth.ts): Added Google and GitHub social login support viabetter-auth/social-providers. Thegoogle()andgithub()plugins are conditionally loaded whenGOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRETandGITHUB_CLIENT_ID/GITHUB_CLIENT_SECRETenv vars are present.apps/api/src/lib/auth.ts): AddedgetActiveProviders()function that enumerates configured OAuth/social providers.apps/api/src/index.ts): Added public/api/auth/providersendpoint returning the list of active providers (google, github, authentik) so the frontend knows what login buttons to render.apps/web/src/App.tsx): UpdatedLoginPageto fetch active providers from/api/auth/providersand render Google and GitHub buttons alongside the existing SSO (Authentik) button when those providers are configured.infra/apps/groombook/overlays/prod/): Createdsocial-auth-sealed-secret.yamlwith placeholder values for social login credentials (CEO needs to provide real values).infra/apps/groombook/overlays/prod/): Updatedapi-patch.yamlto sourceGOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRETfrom the new sealed secret and removed OIDC/Authentik env vars (Demo uses social login, not Authentik).Acceptance Criteria
auth.tssupports Google and GitHub social providers when env vars are presentDependencies
https://groombook.farh.net/api/auth/callback/google)https://groombook.farh.net/api/auth/callback/github)social-auth-sealed-secret.yamlwith real encrypted values viakubesealcc @cpfarhood
Deployed to groombook-dev
Images:
pr-249URL: https://dev.groombook.farh.net
Ready for UAT validation.
QA Review: Changes Requested
The PR code is correct (auth providers, login buttons, /api/auth/providers endpoint), but infra overlay changes are missing.
Missing: Acceptance Criteria #6
Required: Update :
What passed
What needs to change
Add the infra overlay files to this PR or clarify where the sealed secret manifest and env var overrides are managed (given infra is a submodule).
QA Review: Changes Requested
The PR code is correct (auth providers, login buttons, /api/auth/providers endpoint), but infra overlay changes are missing.
Missing: Acceptance Criteria #6
Required: Update
infra/apps/groombook/overlays/prod/:What passed
What needs to change
Add the infra overlay files to this PR or clarify where the sealed secret manifest and env var overrides are managed (given infra is a submodule).
QA Review: APPROVED
PR: #249
CI Checks: ALL PASS
Code Review: PASS
Reviewed 3 changed files:
apps/api/src/lib/auth.ts — Correctly adds and social providers from , conditionally enabled when / and / env vars are present. correctly enumerates available providers.
apps/api/src/index.ts — New endpoint exposes active providers to frontend without requiring auth. Correct.
apps/web/src/App.tsx — fetches and renders Google/GitHub buttons conditionally. Graceful fallback if fetch fails. No regression to Authentik/dev paths.
OOBE compatibility — Existing flow ( + ) handles any authenticated user with email claim; social login tokens provide email claims. No code change needed.
Infra Overlay (Acceptance Criteria #6)
The CTO confirmed infra overlay changes are committed separately in at commit (separate git repo from app repo). Sealed secret placeholder + for prod overlay are not in the PR diff because the infra is an independently-managed submodule.
Verdict: APPROVE. Handing off to CTO for merge and UAT promotion.
QA Review: APPROVED
PR: https://github.com/groombook/groombook/pull/249
CI Checks: ALL PASS
Code Review: PASS
Reviewed 3 changed files:
apps/api/src/lib/auth.ts — Correctly adds google() and github() social providers from better-auth/social-providers, conditionally enabled when GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET and GITHUB_CLIENT_ID/GITHUB_CLIENT_SECRET env vars are present. getActiveProviders() correctly enumerates available providers.
apps/api/src/index.ts — New /api/auth/providers endpoint exposes active providers to frontend without requiring auth. Correct.
apps/web/src/App.tsx — LoginPage fetches /api/auth/providers and renders Google/GitHub buttons conditionally. Graceful fallback if fetch fails. No regression to Authentik/dev paths.
OOBE compatibility — Existing flow (/api/setup + SetupWizard.jsx) handles any authenticated user with email claim; social login tokens provide email claims. No code change needed.
Infra Overlay (Acceptance Criteria #6)
CTO confirmed infra overlay changes are committed separately in groombook/infra at commit 44c4135 (separate git repo from app repo). Sealed secret placeholder + api-patch.yaml for prod overlay are not in PR diff because infra is an independently-managed submodule.
Verdict: APPROVE. Handing off to CTO for merge and UAT promotion.
CTO Review: APPROVED
Code is clean and correct:
getActiveProviders()properly enumerates configured providers. Social plugins correctly spread into the Better-Auth plugins array./api/auth/providersendpoint returns only provider names (no secrets). Placed before auth middleware correctly.44c4135).No security concerns. No regressions for UAT (Authentik) or dev (AUTH_DISABLED).
LGTM — merging now.
Security Review — GRO-531 Social Login
Reviewer: Barkley Trimsworth, Security Engineer
Date: 2026-04-10
PR: #249 — → (MERGED)
Summary
The social login implementation adds Google and GitHub OAuth providers via . Code review completed; no critical or high-severity security findings.
Findings
1. endpoint — No Issue
File:
The new public endpoint returns only provider identifier strings (, , ). No secrets, tokens, or user data exposed. Appropriate for a public login-page configuration endpoint.
2. — No Issue
File:
Returns hardcoded provider names based on env var presence. No user-controlled input. String values are allowlisted (not reflected from user input).
3. Social provider credentials — No Issue
File:
, , , are server-side only (read from env vars, never exposed to client). Passed only to 's plugin initialization.
4. Login page social buttons — No Issue
File:
Provider names rendered in JSX are from the server-controlled response (hardcoded strings). receives provider from the allowlisted array, not from user input.
5. OAuth callback URL — Informational
File:
The is client-side. However, this is mitigated by:
Recommendation: Verify with your OAuth provider settings that the exact callback URLs match:
6. Sealed secret placeholders — Action Required
File:
Contains placeholder values (, etc.). The CEO must provide real credentials and regenerate the sealed secrets via before Demo goes live. Do not deploy to production with placeholder values.
7. Trusted origins — OK
File:
The fallback to localhost is only active when is unset (dev). In prod overlays, is explicitly set to the production domain.
Dependencies
The new package was introduced. No known vulnerabilities identified at time of review, but recommend running and monitoring CVE feeds for .
Security Posture: APPROVED ✓
The implementation follows secure coding practices:
Remaining blocker before Demo production: CEO must provide real Google/GitHub OAuth credentials and regenerate .
*cc @cpfarhood for visibility
Security Review — GRO-531 Social Login
Reviewer: Barkley Trimsworth, Security Engineer
Date: 2026-04-10
PR: #249 —
fix/gro-531-social-login→main(MERGED)Summary
The social login implementation adds Google and GitHub OAuth providers via
better-auth/social-providers. Code review completed; no critical or high-severity security findings.Findings
1.
/api/auth/providersendpoint — No IssueFile:
apps/api/src/index.ts:96-98The new public endpoint returns only provider identifier strings (
google,github,authentik). No secrets, tokens, or user data exposed. Appropriate for a public login-page configuration endpoint.2.
getActiveProviders()— No IssueFile:
apps/api/src/lib/auth.ts:32-44Returns hardcoded provider names based on env var presence. No user-controlled input. String values are allowlisted (not reflected from user input).
3. Social provider credentials — No Issue
File:
apps/api/src/lib/auth.ts:171-186GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRETare server-side only (read from env vars, never exposed to client). Passed only tobetter-auth's plugin initialization.4. Login page social buttons — No Issue
File:
apps/web/src/App.tsx:68-150Provider names rendered in JSX are from the server-controlled
/api/auth/providersresponse (hardcoded strings).handleSocialLoginreceives provider from the allowlisted array, not from user input.5. OAuth callback URL — Informational
File:
apps/web/src/App.tsx:36The
callbackURLis client-side. However, this is mitigated by:stateparameter (CSRF token) in the OAuth flowRecommendation: Verify with your OAuth provider settings that the exact callback URLs match:
https://groombook.farh.net/api/auth/callback/googlehttps://groombook.farh.net/api/auth/callback/github6. Sealed secret placeholders — Action Required
File:
infra/apps/groombook/overlays/prod/social-auth-sealed-secret.yamlContains placeholder values (
REPLACE_WITH_REAL_GOOGLE_CLIENT_ID, etc.). The CEO must provide real credentials and regenerate the sealed secrets viakubesealbefore Demo goes live. Do not deploy to production with placeholder values.7. Trusted origins — OK
File:
apps/api/src/lib/auth.ts:225trustedOrigins: [process.env.CORS_ORIGIN ?? "http://localhost:5173"]The fallback to localhost is only active when
CORS_ORIGINis unset (dev). In prod overlays,CORS_ORIGINis explicitly set to the production domain.Dependencies
The new
better-auth/social-providerspackage was introduced. No known vulnerabilities identified at time of review, but recommend runningnpm auditand monitoring CVE feeds forbetter-auth.Security Posture: APPROVED ✓
The implementation follows secure coding practices:
stateparameterRemaining blocker before Demo production: CEO must provide real Google/GitHub OAuth credentials and regenerate
social-auth-sealed-secret.yaml.cc @cpfarhood for visibility