From b9b1c995f9d5cd43991c0c84ddd0b0369551f828 Mon Sep 17 00:00:00 2001 From: Leo Vasanko Date: Thu, 4 Dec 2025 01:58:18 +0000 Subject: [PATCH] Update forward API to return in JSON iframe srcdoc with options injected. (currently broken in dev mode). --- examples/restricted-api.html | 37 +++++++++++++++---- frontend/auth/App.vue | 9 ++--- frontend/auth/admin/AdminApp.vue | 7 ++-- frontend/auth/restricted/RestrictedApi.vue | 8 +++-- frontend/src/utils/api.js | 42 +++++++++++++++++++--- passkey/fastapi/admin.py | 9 +---- passkey/fastapi/api.py | 26 +++----------- passkey/fastapi/authz.py | 20 ++++++++++- passkey/fastapi/user.py | 9 +---- passkey/fastapi/ws.py | 7 +--- 10 files changed, 111 insertions(+), 63 deletions(-) diff --git a/examples/restricted-api.html b/examples/restricted-api.html index 60fc2af..3c6f094 100644 --- a/examples/restricted-api.html +++ b/examples/restricted-api.html @@ -103,7 +103,32 @@ } }); - function showLoginMode() { + // Cache for auth iframe HTML by mode + const authIframeHtmlCache = {}; + + async function getAuthIframeHtml(mode = 'login') { + if (authIframeHtmlCache[mode]) { + return authIframeHtmlCache[mode]; + } + + // Fetch from forward endpoint - it returns HTML in auth.iframe on 401/403 + const response = await fetch('/auth/api/forward', { credentials: 'include' }); + if (response.status === 401 || response.status === 403) { + const data = await response.json(); + if (data.auth?.iframe) { + let html = data.auth.iframe; + if (mode !== data.auth.mode) { + // Replace data-mode attribute value + html = html.replace(/data-mode="[^"]*"/, `data-mode="${mode}"`); + } + authIframeHtmlCache[mode] = html; + return html; + } + } + throw new Error('Unable to fetch auth iframe HTML'); + } + + async function showLoginMode() { let iframe = document.getElementById('auth-iframe'); if (!iframe) { iframe = document.createElement('iframe'); @@ -111,11 +136,11 @@ iframe.title = 'Authentication'; document.body.appendChild(iframe); } - iframe.src = '/auth/restricted/?mode=login'; + iframe.srcdoc = await getAuthIframeHtml('login'); showStatus('Login mode loaded - for users who are not authenticated', 'info'); } - function showReauthMode() { + async function showReauthMode() { let iframe = document.getElementById('auth-iframe'); if (!iframe) { iframe = document.createElement('iframe'); @@ -123,17 +148,17 @@ iframe.title = 'Authentication'; document.body.appendChild(iframe); } - iframe.src = '/auth/restricted/?mode=reauth'; + iframe.srcdoc = await getAuthIframeHtml('reauth'); showStatus('Reauth mode loaded - for additional verification of authenticated users', 'info'); } - function showAuthIframe() { + async function showAuthIframe() { let iframe = document.getElementById('auth-iframe'); if (!iframe) { iframe = document.createElement('iframe'); iframe.id = 'auth-iframe'; iframe.title = 'Authentication'; - iframe.src = '/auth/restricted/'; + iframe.srcdoc = await getAuthIframeHtml('login'); document.body.appendChild(iframe); iframeInitialized = true; } diff --git a/frontend/auth/App.vue b/frontend/auth/App.vue index a583f83..ee63824 100644 --- a/frontend/auth/App.vue +++ b/frontend/auth/App.vue @@ -12,7 +12,7 @@