mirror of
https://github.com/jason5ng32/MyIP.git
synced 2026-11-04 08:55:47 +00:00
Refactor(auth): one auth domain per deployment
VITE_FIREBASE_AUTH_DOMAIN is each environment's own host, served by the /__/auth proxy; the PWA-only VITE_FIREBASE_PWA_AUTH_DOMAIN and utils/auth-domain.js go. Every OAuth provider lists the handler URL per environment (Google and GitHub both take several redirect URIs). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
This commit is contained in:
6 files changed
+13
-77
No files matched your search
+6
-10
@@ -38,18 +38,14 @@ VITE_PULSE_BEACON_URL=""
|
||||
VITE_CURL_IPV4_DOMAIN=""
|
||||
VITE_CURL_IPV6_DOMAIN=""
|
||||
VITE_CURL_IPV64_DOMAIN=""
|
||||
# Firebase Auth — optional; sign-in is offered when API key, auth domain and
|
||||
# project id are all set. VITE_FIREBASE_AUTH_DOMAIN is the browsers' login
|
||||
# domain (e.g. "auth.ipcheck.ing"); each OAuth provider's callback URL is
|
||||
# https://<that domain>/__/auth/handler.
|
||||
# VITE_FIREBASE_PWA_AUTH_DOMAIN — optional, installed PWA only: the site's own
|
||||
# host (e.g. "ipcheck.ing"), served by the /__/auth proxy. Add it to Firebase
|
||||
# Authentication → Authorized domains, and https://<it>/__/auth/handler to
|
||||
# every OAuth provider (Google: an extra redirect URI; GitHub: an extra
|
||||
# redirect URI, or wildcard matching on the apex callback).
|
||||
# Firebase Auth — optional; sign-in is offered when all three are set.
|
||||
# VITE_FIREBASE_AUTH_DOMAIN is this deployment's own host (e.g. "ipcheck.ing"):
|
||||
# the frontend server and Vite proxy /__/auth/* to Firebase for it, which the
|
||||
# installed PWA needs. Add the host to Firebase Authentication → Authorized
|
||||
# domains and https://<host>/__/auth/handler to every OAuth provider's
|
||||
# redirect URIs (one per environment, or GitHub's wildcard matching).
|
||||
VITE_FIREBASE_API_KEY=""
|
||||
VITE_FIREBASE_AUTH_DOMAIN=""
|
||||
VITE_FIREBASE_PWA_AUTH_DOMAIN=""
|
||||
VITE_FIREBASE_PROJECT_ID=""
|
||||
# Google Analytics
|
||||
VITE_GOOGLE_ANALYTICS_ID=""
|
||||
|
||||
+5
-6
@@ -161,12 +161,11 @@ upstreams; those get only what's explicitly needed.
|
||||
|
||||
`frontend-server.js` (production) and `vite.config.js` (dev) reverse-proxy
|
||||
`/__/auth/*` to `<projectId>.firebaseapp.com` (`common/firebase-auth-proxy.js`)
|
||||
when `VITE_FIREBASE_PROJECT_ID` is set. `VITE_FIREBASE_PWA_AUTH_DOMAIN` points
|
||||
the installed PWA at the site's own host, so its sign-in handler runs
|
||||
first-party — inside the PWA's webview and Safari's storage partition — and
|
||||
`getRedirectResult` finds the result; browsers keep the shared
|
||||
`VITE_FIREBASE_AUTH_DOMAIN`. Every OAuth provider must accept
|
||||
`https://<host>/__/auth/handler` for both domains. Not an `/api` route: no
|
||||
when `VITE_FIREBASE_PROJECT_ID` is set, so `VITE_FIREBASE_AUTH_DOMAIN` can be
|
||||
the deployment's own host and the sign-in handler runs first-party — inside
|
||||
the installed PWA's webview and Safari's storage partition, where
|
||||
`getRedirectResult` finds the result. Every OAuth provider must accept
|
||||
`https://<host>/__/auth/handler` per environment. Not an `/api` route: no
|
||||
guards, caching or per-request logs.
|
||||
|
||||
## Edge caching
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ over copied-in shadcn-vue primitives. No TypeScript, no `dark:` dual pairs.
|
||||
frontend/
|
||||
├── App.vue / main.js / store.js / router/ / locales/ / style/style.css
|
||||
├── firebase-init.js ← env-gated lazy Firebase Auth (boot path: utils/auth-hint.js;
|
||||
│ PWA / blocked-popup redirect sign-in: utils/auth-redirect.js;
|
||||
│ the PWA's own auth domain: utils/auth-domain.js)
|
||||
│ PWA / blocked-popup redirect sign-in: utils/auth-redirect.js)
|
||||
├── sentry-init.js ← env-gated Sentry (see "Error monitoring")
|
||||
├── data/ ← static config (tools registry drives pages+cards+nav)
|
||||
├── lib/ · utils/ · composables/ ← see "Helper placement"
|
||||
|
||||
@@ -1,20 +1,10 @@
|
||||
// Firebase Auth bootstrap — env-gated AND lazy: the SDK chunk only loads on
|
||||
// the first loadFirebaseAuth() call (signed-in boot, sign-in click, or the
|
||||
// background auth probe), never on the visitor-critical path.
|
||||
import { resolveAuthDomain } from './utils/auth-domain.js';
|
||||
import { isRunningAsPwa } from './utils/pwa.js';
|
||||
|
||||
const env = import.meta.env ?? {};
|
||||
|
||||
const isFireBaseSet = !!env.VITE_FIREBASE_API_KEY && !!env.VITE_FIREBASE_AUTH_DOMAIN && !!env.VITE_FIREBASE_PROJECT_ID;
|
||||
|
||||
// Inputs for utils/auth-domain.js, read on demand (display mode needs `window`).
|
||||
const authDomainInputs = () => ({
|
||||
runningAsPwa: isRunningAsPwa(),
|
||||
authDomain: env.VITE_FIREBASE_AUTH_DOMAIN,
|
||||
pwaAuthDomain: env.VITE_FIREBASE_PWA_AUTH_DOMAIN,
|
||||
});
|
||||
|
||||
let authModulePromise = null;
|
||||
|
||||
// Resolves to the firebase/auth namespace plus the initialized `auth`
|
||||
@@ -35,7 +25,7 @@ const loadFirebaseAuth = () => {
|
||||
...authModule,
|
||||
auth: authModule.getAuth(appModule.initializeApp({
|
||||
apiKey: env.VITE_FIREBASE_API_KEY,
|
||||
authDomain: resolveAuthDomain(authDomainInputs()),
|
||||
authDomain: env.VITE_FIREBASE_AUTH_DOMAIN,
|
||||
projectId: env.VITE_FIREBASE_PROJECT_ID,
|
||||
})),
|
||||
};
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
// Which Firebase auth domain this session signs in through: browsers keep
|
||||
// the shared default, the installed PWA may use VITE_FIREBASE_PWA_AUTH_DOMAIN
|
||||
// (why: api/AGENTS.md "Firebase Auth handler proxy").
|
||||
|
||||
const clean = (value) => (typeof value === 'string' ? value.trim() : '');
|
||||
|
||||
// The domain to initialise Firebase with; a blank PWA value means unset.
|
||||
export const resolveAuthDomain = ({ runningAsPwa, authDomain, pwaAuthDomain }) => {
|
||||
const fallback = clean(authDomain);
|
||||
if (!runningAsPwa) return fallback;
|
||||
return clean(pwaAuthDomain) || fallback;
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
// Tests for the auth-domain choice (frontend/utils/auth-domain.js): browsers
|
||||
// keep the shared default domain, the installed PWA may use its own, and
|
||||
// GitHub (one callback, on the default domain) drops out when it does.
|
||||
|
||||
import assert from 'node:assert/strict';
|
||||
import { describe, it } from 'node:test';
|
||||
import { resolveAuthDomain } from '../frontend/utils/auth-domain.js';
|
||||
|
||||
const DEFAULT = 'auth.example.com';
|
||||
const SITE = 'example.com';
|
||||
|
||||
describe('resolveAuthDomain', () => {
|
||||
it('uses the default domain in a browser tab, even with a PWA domain set', () => {
|
||||
assert.equal(resolveAuthDomain({ runningAsPwa: false, authDomain: DEFAULT, pwaAuthDomain: SITE }), DEFAULT);
|
||||
});
|
||||
|
||||
it('uses the PWA domain inside the installed PWA', () => {
|
||||
assert.equal(resolveAuthDomain({ runningAsPwa: true, authDomain: DEFAULT, pwaAuthDomain: SITE }), SITE);
|
||||
});
|
||||
|
||||
it('falls back to the default in the PWA when the PWA domain is unset or blank', () => {
|
||||
assert.equal(resolveAuthDomain({ runningAsPwa: true, authDomain: DEFAULT }), DEFAULT);
|
||||
assert.equal(resolveAuthDomain({ runningAsPwa: true, authDomain: DEFAULT, pwaAuthDomain: '' }), DEFAULT);
|
||||
assert.equal(resolveAuthDomain({ runningAsPwa: true, authDomain: DEFAULT, pwaAuthDomain: ' ' }), DEFAULT);
|
||||
});
|
||||
|
||||
it('trims both values', () => {
|
||||
assert.equal(resolveAuthDomain({ runningAsPwa: false, authDomain: ` ${DEFAULT} ` }), DEFAULT);
|
||||
assert.equal(resolveAuthDomain({ runningAsPwa: true, authDomain: DEFAULT, pwaAuthDomain: ` ${SITE}\n` }), SITE);
|
||||
});
|
||||
|
||||
it('returns an empty string when nothing is configured', () => {
|
||||
assert.equal(resolveAuthDomain({ runningAsPwa: false }), '');
|
||||
assert.equal(resolveAuthDomain({ runningAsPwa: true }), '');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user