fix(auth): refresh Auth0 config from server every load to clear stale localStorage domain
Made-with: Cursor
This commit is contained in:
59
index.html
59
index.html
@@ -753,10 +753,35 @@
|
|||||||
return pathname;
|
return pathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildAuthConfigBase() {
|
||||||
|
const cfg = window.AUTH_CONFIG && typeof window.AUTH_CONFIG === "object" ? window.AUTH_CONFIG : {};
|
||||||
|
const auth0 = cfg.auth0 && typeof cfg.auth0 === "object" ? cfg.auth0 : {};
|
||||||
|
const connections = cfg.connections && typeof cfg.connections === "object" ? cfg.connections : {};
|
||||||
|
const adminEmails = Array.isArray(cfg.adminEmails)
|
||||||
|
? cfg.adminEmails
|
||||||
|
: Array.isArray(cfg.allowedEmails)
|
||||||
|
? cfg.allowedEmails
|
||||||
|
: [];
|
||||||
|
return {
|
||||||
|
auth0: {
|
||||||
|
domain: String(auth0.domain || "").trim(),
|
||||||
|
clientId: String(auth0.clientId || "").trim(),
|
||||||
|
},
|
||||||
|
connections: {
|
||||||
|
google: String(connections.google || "").trim(),
|
||||||
|
kakao: String(connections.kakao || "").trim(),
|
||||||
|
naver: String(connections.naver || "").trim(),
|
||||||
|
},
|
||||||
|
adminEmails: adminEmails.map((e) => String(e).trim().toLowerCase()).filter(Boolean),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function hydrateAuthConfigFromServerIfNeeded() {
|
async function hydrateAuthConfigFromServerIfNeeded() {
|
||||||
const cfg = getAuthConfig();
|
const embedded = buildAuthConfigBase();
|
||||||
const hasLocal = Boolean(cfg.auth0.domain && cfg.auth0.clientId && cfg.connections.google);
|
const fullyInPage = Boolean(
|
||||||
if (hasLocal) return true;
|
embedded.auth0.domain && embedded.auth0.clientId && embedded.connections.google
|
||||||
|
);
|
||||||
|
if (fullyInPage) return true;
|
||||||
try {
|
try {
|
||||||
const r = await fetch(apiUrl("/api/config/auth"), { cache: "no-store" });
|
const r = await fetch(apiUrl("/api/config/auth"), { cache: "no-store" });
|
||||||
if (!r.ok) return false;
|
if (!r.ok) return false;
|
||||||
@@ -765,6 +790,11 @@
|
|||||||
const v = data.value;
|
const v = data.value;
|
||||||
const auth0 = v.auth0 || {};
|
const auth0 = v.auth0 || {};
|
||||||
const connections = v.connections || {};
|
const connections = v.connections || {};
|
||||||
|
const adminEmails = Array.isArray(v.adminEmails)
|
||||||
|
? v.adminEmails
|
||||||
|
: Array.isArray(v.allowedEmails)
|
||||||
|
? v.allowedEmails
|
||||||
|
: [];
|
||||||
const domain = String(auth0.domain || "").trim();
|
const domain = String(auth0.domain || "").trim();
|
||||||
const clientId = String(auth0.clientId || "").trim();
|
const clientId = String(auth0.clientId || "").trim();
|
||||||
const google = String(connections.google || "").trim();
|
const google = String(connections.google || "").trim();
|
||||||
@@ -774,6 +804,7 @@
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
auth0: { domain, clientId },
|
auth0: { domain, clientId },
|
||||||
connections: { google },
|
connections: { google },
|
||||||
|
adminEmails: adminEmails.map((e) => String(e).trim().toLowerCase()).filter(Boolean),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
@@ -817,27 +848,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getAuthConfig() {
|
function getAuthConfig() {
|
||||||
const cfg = window.AUTH_CONFIG && typeof window.AUTH_CONFIG === "object" ? window.AUTH_CONFIG : {};
|
const base = buildAuthConfigBase();
|
||||||
const auth0 = cfg.auth0 && typeof cfg.auth0 === "object" ? cfg.auth0 : {};
|
|
||||||
const connections = cfg.connections && typeof cfg.connections === "object" ? cfg.connections : {};
|
|
||||||
// legacy: allowedEmails -> adminEmails
|
|
||||||
const adminEmails = Array.isArray(cfg.adminEmails)
|
|
||||||
? cfg.adminEmails
|
|
||||||
: Array.isArray(cfg.allowedEmails)
|
|
||||||
? cfg.allowedEmails
|
|
||||||
: [];
|
|
||||||
const base = {
|
|
||||||
auth0: {
|
|
||||||
domain: String(auth0.domain || "").trim(),
|
|
||||||
clientId: String(auth0.clientId || "").trim(),
|
|
||||||
},
|
|
||||||
connections: {
|
|
||||||
google: String(connections.google || "").trim(),
|
|
||||||
kakao: String(connections.kakao || "").trim(),
|
|
||||||
naver: String(connections.naver || "").trim(),
|
|
||||||
},
|
|
||||||
adminEmails: adminEmails.map((e) => String(e).trim().toLowerCase()).filter(Boolean),
|
|
||||||
};
|
|
||||||
const over = loadAuthOverride();
|
const over = loadAuthOverride();
|
||||||
if (!over) return base;
|
if (!over) return base;
|
||||||
return {
|
return {
|
||||||
|
|||||||
41
script.js
41
script.js
@@ -532,42 +532,47 @@
|
|||||||
localStorage.removeItem(AUTH_OVERRIDE_KEY);
|
localStorage.removeItem(AUTH_OVERRIDE_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAuthConfig() {
|
/** index.html(window.AUTH_CONFIG)만 반영. localStorage 캐시는 포함하지 않음. */
|
||||||
|
function buildAuthConfigBase() {
|
||||||
const cfg = globalThis.AUTH_CONFIG && typeof globalThis.AUTH_CONFIG === "object" ? globalThis.AUTH_CONFIG : {};
|
const cfg = globalThis.AUTH_CONFIG && typeof globalThis.AUTH_CONFIG === "object" ? globalThis.AUTH_CONFIG : {};
|
||||||
const apiBase = String(cfg.apiBase || "").trim(); // optional, e.g. https://api.ncue.net
|
const apiBase = String(cfg.apiBase || "").trim();
|
||||||
const auth0 = cfg.auth0 && typeof cfg.auth0 === "object" ? cfg.auth0 : {};
|
const auth0 = cfg.auth0 && typeof cfg.auth0 === "object" ? cfg.auth0 : {};
|
||||||
// legacy: allowedEmails -> adminEmails
|
const conn = cfg.connections && typeof cfg.connections === "object" ? cfg.connections : {};
|
||||||
const adminEmails = Array.isArray(cfg.adminEmails)
|
const adminEmails = Array.isArray(cfg.adminEmails)
|
||||||
? cfg.adminEmails
|
? cfg.adminEmails
|
||||||
: Array.isArray(cfg.allowedEmails)
|
: Array.isArray(cfg.allowedEmails)
|
||||||
? cfg.allowedEmails
|
? cfg.allowedEmails
|
||||||
: [];
|
: [];
|
||||||
const base = {
|
return {
|
||||||
apiBase,
|
apiBase,
|
||||||
auth0: {
|
auth0: {
|
||||||
domain: String(auth0.domain || "").trim(),
|
domain: String(auth0.domain || "").trim(),
|
||||||
clientId: String(auth0.clientId || "").trim(),
|
clientId: String(auth0.clientId || "").trim(),
|
||||||
},
|
},
|
||||||
connections: {
|
connections: {
|
||||||
google: "",
|
google: String(conn.google || "").trim(),
|
||||||
kakao: "",
|
kakao: String(conn.kakao || "").trim(),
|
||||||
naver: "",
|
naver: String(conn.naver || "").trim(),
|
||||||
},
|
},
|
||||||
adminEmails: adminEmails.map((e) => String(e).trim().toLowerCase()).filter(Boolean),
|
adminEmails: adminEmails.map((e) => String(e).trim().toLowerCase()).filter(Boolean),
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAuthConfig() {
|
||||||
|
const base = buildAuthConfigBase();
|
||||||
const override = loadAuthOverride();
|
const override = loadAuthOverride();
|
||||||
if (!override) return base;
|
if (!override) return base;
|
||||||
// override가 있으면 우선 적용 (서버 재배포 없이 테스트 가능)
|
// 서버에서 받아 둔 캐시(또는 예전 잘못된 값). 서버 .env 수정 후에는 hydrate가 덮어씀.
|
||||||
return {
|
return {
|
||||||
apiBase,
|
apiBase: base.apiBase,
|
||||||
auth0: {
|
auth0: {
|
||||||
domain: override.auth0.domain || base.auth0.domain,
|
domain: override.auth0.domain || base.auth0.domain,
|
||||||
clientId: override.auth0.clientId || base.auth0.clientId,
|
clientId: override.auth0.clientId || base.auth0.clientId,
|
||||||
},
|
},
|
||||||
connections: {
|
connections: {
|
||||||
google: override.connections?.google || "",
|
google: override.connections?.google || base.connections.google,
|
||||||
kakao: override.connections?.kakao || "",
|
kakao: override.connections?.kakao || base.connections.kakao,
|
||||||
naver: override.connections?.naver || "",
|
naver: override.connections?.naver || base.connections.naver,
|
||||||
},
|
},
|
||||||
adminEmails: override.adminEmails.length ? override.adminEmails : base.adminEmails,
|
adminEmails: override.adminEmails.length ? override.adminEmails : base.adminEmails,
|
||||||
};
|
};
|
||||||
@@ -585,9 +590,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function hydrateAuthConfigFromServerIfNeeded() {
|
async function hydrateAuthConfigFromServerIfNeeded() {
|
||||||
const cfg = getAuthConfig();
|
const embedded = buildAuthConfigBase();
|
||||||
const hasLocal = Boolean(cfg.auth0.domain && cfg.auth0.clientId && cfg.connections.google);
|
const fullyInPage = Boolean(
|
||||||
if (hasLocal) return true;
|
embedded.auth0.domain && embedded.auth0.clientId && embedded.connections.google
|
||||||
|
);
|
||||||
|
// index에 Auth0 전부 박혀 있으면 서버 조회 생략(오프라인/별도 배포용)
|
||||||
|
if (fullyInPage) return true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const r = await fetch(apiUrl("/api/config/auth"), { cache: "no-store" });
|
const r = await fetch(apiUrl("/api/config/auth"), { cache: "no-store" });
|
||||||
if (!r.ok) return false;
|
if (!r.ok) return false;
|
||||||
@@ -596,7 +605,6 @@
|
|||||||
const v = data.value;
|
const v = data.value;
|
||||||
const auth0 = v.auth0 || {};
|
const auth0 = v.auth0 || {};
|
||||||
const connections = v.connections || {};
|
const connections = v.connections || {};
|
||||||
// legacy: allowedEmails -> adminEmails
|
|
||||||
const adminEmails = Array.isArray(v.adminEmails)
|
const adminEmails = Array.isArray(v.adminEmails)
|
||||||
? v.adminEmails
|
? v.adminEmails
|
||||||
: Array.isArray(v.allowedEmails)
|
: Array.isArray(v.allowedEmails)
|
||||||
@@ -606,6 +614,7 @@
|
|||||||
const clientId = String(auth0.clientId || "").trim();
|
const clientId = String(auth0.clientId || "").trim();
|
||||||
const google = String(connections.google || "").trim();
|
const google = String(connections.google || "").trim();
|
||||||
if (!domain || !clientId || !google) return false;
|
if (!domain || !clientId || !google) return false;
|
||||||
|
// 예전 버전: 잘못된 도메인이 localStorage에 남으면 hydrate를 건너뛰어 영구 고착됨 → 매 로드마다 덮어씀
|
||||||
saveAuthOverride({
|
saveAuthOverride({
|
||||||
auth0: { domain, clientId },
|
auth0: { domain, clientId },
|
||||||
connections: { google },
|
connections: { google },
|
||||||
|
|||||||
Reference in New Issue
Block a user