Wire quick login in fallback mode
When external script.js fails and inline fallback runs, connect Naver/Kakao/Google buttons to Auth0 loginWithRedirect (by connection) and show logout/user state after authentication. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
154
index.html
154
index.html
@@ -22,10 +22,18 @@
|
||||
// 2) Allowed Callback URLs / Allowed Logout URLs에 현재 사이트 주소를 등록하세요.
|
||||
// 예: https://drive.daewoongai.com/apps/dashboard/
|
||||
window.AUTH_CONFIG = {
|
||||
// end-user가 설정 모달을 사용하는지 여부(기본: false)
|
||||
allowEndUserConfig: false,
|
||||
auth0: {
|
||||
domain: "",
|
||||
clientId: "",
|
||||
},
|
||||
// Auth0 connection 이름(선택). 예: google-oauth2 / kakao / naver
|
||||
connections: {
|
||||
google: "",
|
||||
kakao: "",
|
||||
naver: "",
|
||||
},
|
||||
// 관리 허용 이메일(대소문자 무시)
|
||||
allowedEmails: [],
|
||||
};
|
||||
@@ -383,6 +391,7 @@
|
||||
|
||||
const STORAGE_KEY = "links_home_v1";
|
||||
const THEME_KEY = "links_home_theme_v1";
|
||||
const AUTH_OVERRIDE_KEY = "links_home_auth_override_v1";
|
||||
|
||||
const el = {
|
||||
q: document.getElementById("q"),
|
||||
@@ -395,6 +404,13 @@
|
||||
btnImport: document.getElementById("btnImport"),
|
||||
btnExport: document.getElementById("btnExport"),
|
||||
btnTheme: document.getElementById("btnTheme"),
|
||||
snsLogin: document.getElementById("snsLogin"),
|
||||
btnNaver: document.getElementById("btnNaver"),
|
||||
btnKakao: document.getElementById("btnKakao"),
|
||||
btnGoogle: document.getElementById("btnGoogle"),
|
||||
btnLogout: document.getElementById("btnLogout"),
|
||||
user: document.getElementById("user"),
|
||||
userText: document.getElementById("userText"),
|
||||
toast: document.getElementById("toast"),
|
||||
modal: document.getElementById("modal"),
|
||||
btnClose: document.getElementById("btnClose"),
|
||||
@@ -662,6 +678,138 @@
|
||||
applyTheme(prefersLight ? "light" : "dark");
|
||||
})();
|
||||
|
||||
// Auth (fallback): wire SNS quick login buttons
|
||||
const auth = {
|
||||
client: null,
|
||||
user: null,
|
||||
ready: false,
|
||||
};
|
||||
|
||||
function loadAuthOverride() {
|
||||
const raw = localStorage.getItem(AUTH_OVERRIDE_KEY);
|
||||
const data = raw ? safeJsonParse(raw, null) : null;
|
||||
if (!data || typeof data !== "object") return null;
|
||||
const auth0 = data.auth0 && typeof data.auth0 === "object" ? data.auth0 : {};
|
||||
const connections = data.connections && typeof data.connections === "object" ? data.connections : {};
|
||||
const allowedEmails = Array.isArray(data.allowedEmails) ? data.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(),
|
||||
},
|
||||
allowedEmails: allowedEmails.map((e) => String(e).trim().toLowerCase()).filter(Boolean),
|
||||
};
|
||||
}
|
||||
|
||||
function getAuthConfig() {
|
||||
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 allowedEmails = 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(),
|
||||
},
|
||||
allowedEmails: allowedEmails.map((e) => String(e).trim().toLowerCase()).filter(Boolean),
|
||||
};
|
||||
const over = loadAuthOverride();
|
||||
if (!over) return base;
|
||||
return {
|
||||
auth0: {
|
||||
domain: over.auth0.domain || base.auth0.domain,
|
||||
clientId: over.auth0.clientId || base.auth0.clientId,
|
||||
},
|
||||
connections: {
|
||||
google: over.connections.google || base.connections.google,
|
||||
kakao: over.connections.kakao || base.connections.kakao,
|
||||
naver: over.connections.naver || base.connections.naver,
|
||||
},
|
||||
allowedEmails: over.allowedEmails.length ? over.allowedEmails : base.allowedEmails,
|
||||
};
|
||||
}
|
||||
|
||||
function currentUrlNoQuery() {
|
||||
const u = new URL(location.href);
|
||||
u.searchParams.delete("code");
|
||||
u.searchParams.delete("state");
|
||||
return u.toString();
|
||||
}
|
||||
|
||||
async function ensureAuthClient() {
|
||||
if (auth.client) return auth.client;
|
||||
const cfg = getAuthConfig();
|
||||
if (!cfg.auth0.domain || !cfg.auth0.clientId) return null;
|
||||
if (typeof window.createAuth0Client !== "function") return null;
|
||||
auth.client = await window.createAuth0Client({
|
||||
domain: cfg.auth0.domain,
|
||||
clientId: cfg.auth0.clientId,
|
||||
authorizationParams: {
|
||||
redirect_uri: location.origin === "null" ? location.href : location.origin + location.pathname,
|
||||
},
|
||||
cacheLocation: "localstorage",
|
||||
useRefreshTokens: true,
|
||||
});
|
||||
return auth.client;
|
||||
}
|
||||
|
||||
async function initAuth() {
|
||||
auth.ready = true;
|
||||
const client = await ensureAuthClient();
|
||||
if (!client) {
|
||||
// No config: keep buttons visible but disabled style
|
||||
return;
|
||||
}
|
||||
const u = new URL(location.href);
|
||||
const isCallback = u.searchParams.has("code") && u.searchParams.has("state");
|
||||
if (isCallback) {
|
||||
try {
|
||||
await client.handleRedirectCallback();
|
||||
} finally {
|
||||
history.replaceState({}, document.title, currentUrlNoQuery());
|
||||
}
|
||||
}
|
||||
const isAuthed = await client.isAuthenticated();
|
||||
auth.user = isAuthed ? await client.getUser() : null;
|
||||
if (el.btnLogout) el.btnLogout.hidden = !auth.user;
|
||||
if (el.snsLogin) el.snsLogin.hidden = Boolean(auth.user);
|
||||
if (el.user) el.user.hidden = !auth.user;
|
||||
if (el.userText && auth.user) el.userText.textContent = auth.user.email || auth.user.name || "로그인됨";
|
||||
}
|
||||
|
||||
async function loginWithConnection(provider) {
|
||||
const cfg = getAuthConfig();
|
||||
const client = await ensureAuthClient();
|
||||
if (!client) {
|
||||
toast("간편로그인은 관리자 설정 후 사용 가능합니다.");
|
||||
return;
|
||||
}
|
||||
const conn = cfg.connections[provider] || "";
|
||||
if (!conn) {
|
||||
toast("관리자가 Auth0 connection 이름을 설정해야 합니다.");
|
||||
return;
|
||||
}
|
||||
await client.loginWithRedirect({ authorizationParams: { connection: conn } });
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
const client = await ensureAuthClient();
|
||||
if (!client) return;
|
||||
await client.logout({
|
||||
logoutParams: { returnTo: location.origin === "null" ? location.href : location.origin + location.pathname },
|
||||
});
|
||||
}
|
||||
|
||||
// Wire events
|
||||
if (el.q)
|
||||
el.q.addEventListener("input", () => {
|
||||
@@ -777,7 +925,13 @@
|
||||
applyTheme(cur === "dark" ? "light" : "dark");
|
||||
});
|
||||
|
||||
if (el.btnNaver) el.btnNaver.addEventListener("click", () => loginWithConnection("naver").catch(() => toast("로그인에 실패했습니다.")));
|
||||
if (el.btnKakao) el.btnKakao.addEventListener("click", () => loginWithConnection("kakao").catch(() => toast("로그인에 실패했습니다.")));
|
||||
if (el.btnGoogle) el.btnGoogle.addEventListener("click", () => loginWithConnection("google").catch(() => toast("로그인에 실패했습니다.")));
|
||||
if (el.btnLogout) el.btnLogout.addEventListener("click", () => logout().catch(() => toast("로그아웃에 실패했습니다.")));
|
||||
|
||||
render();
|
||||
initAuth().catch(() => {});
|
||||
toast("스크립트 로딩 문제로 폴백 모드로 실행 중입니다.");
|
||||
}, 200);
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user