ES
SOP-IT-001 · v1.0
Jun 11, 2026

Manual Auth Gate Setup

IT · Google OAuth + @brandacare.com restriction (no DNS migration)

Purpose

Configure the auth gate on manual.brandacare.com so only users with @brandacare.com Google accounts can access. No recurring cost, no DNS migration, no Netlify Pro.

Time: 30 min total  ·  Who: Yami or IT (Quasar/Santi/Manuel)

Important limitation

This is a client-side gate. Deters casual/public access but is NOT cryptographic security:
  • Someone technical can view source with curl/wget (HTML is publicly hosted)
  • JavaScript disabled in browser = no gate
  • Contains NO PHI (PHI lives in Google Apps Script / Workspace — see TRN-IT-001)
For the internal manual (training + SOPs without PHI) this is sufficient. For PHI / sensitive data, NEVER trust client-side auth alone.

Steps

1Create project in Google Cloud Console

  1. Go to console.cloud.google.com
  2. Project selector at top → New Project
  3. Name: BrandaCare Manual Auth
  4. Organization: brandacare.com (should appear if your Workspace is set up correctly)
  5. Create

2Enable Google Identity Services

  1. Sidebar → APIs & ServicesEnabled APIs & services
  2. No extra enablement needed for basic OAuth — Google Identity is default

3Configure OAuth consent screen

  1. Sidebar → APIs & ServicesOAuth consent screen
  2. User Type: Internal (@brandacare.com users only)
  3. Create
  4. App information:
    • App name: BrandaCare Manual
    • User support email: hello@brandacare.com
    • App logo: upload BrandaCare logo (optional)
  5. App domain → Application home page: https://manual.brandacare.com
  6. Authorized domains: brandacare.com
  7. Developer contact: hello@brandacare.com
  8. Save and Continue → Scopes: leave default → Save and Continue → Summary → Back to Dashboard

4Create Credentials (Client ID)

  1. Sidebar → APIs & ServicesCredentials
  2. Click + Create CredentialsOAuth client ID
  3. Application type: Web application
  4. Name: BrandaCare Manual Web Client
  5. Authorized JavaScript origins → + Add URI:
    https://manual.brandacare.com
  6. Authorized redirect URIs → not needed (we use popup mode)
  7. Create
  8. COPY the Client ID shown (like 123456789-abcdef.apps.googleusercontent.com)

5Paste Client ID into auth.js

In your local manual repo, open docs/brand/auth.js:

const CLIENT_ID = 'REPLACE_WITH_YOUR_GOOGLE_OAUTH_CLIENT_ID.apps.googleusercontent.com';

Replace that line with your real Client ID:

const CLIENT_ID = '123456789-abcdef.apps.googleusercontent.com';

6Inject auth gate into all HTMLs

cd "api open dental stedi claims"
python docs/inject_auth.py

Expected output:

🔒 Injecting auth gate into N files...
  ✅ N files modified (0 already had auth gate)

This adds <script src="brand/auth.js"> to each HTML's <head>. Idempotent — running twice doesn't duplicate.

7Re-deploy to Netlify

Drag-and-drop the docs/ folder to Netlify, or if you have CI from Git, push and deploy.

8Verify

  1. Open manual.brandacare.com in incognito tab
  2. BrandaCare-branded login screen should appear
  3. Click "Continue with Google" → log in with @brandacare.com → should enter
  4. Try with personal Gmail (NOT @brandacare.com) → should reject with clear message

Troubleshooting

ErrorCauseFix
Orange "Auth gate not configured" bannerClient ID not replaced in auth.jsEdit brand/auth.js line 15
"Error 400: redirect_uri_mismatch"URI not in Authorized JS originsAdd https://manual.brandacare.com in Google Console → Credentials → your Client ID
"This app isn't verified"OAuth consent screen User Type is ExternalChange to Internal in Google Console
Login works but rejects your @brandacare.comALLOWED_DOMAIN field is wrongCheck auth.js line 16: must be 'brandacare.com' (no @)
HTML changes not showing after editBrowser cacheCmd+Shift+R or incognito

Maintenance

WhenWhat to do
New SOP/training added to manualRe-run python docs/inject_auth.py → re-deploy
Client ID changeEdit brand/auth.js → re-deploy
Compromise suspectedGoogle Cloud → Credentials → regenerate or revoke tokens
Sessions last too longChange SESSION_HOURS in auth.js (default: 8h)

Related