Stop OpenBao login redirect loop by removing URL rewriting

Remove redirect-bootstrap and mount polling that fought Ember's token
fallback. Keep cosmetic overlay and direct KeyCape OIDC on sign-in only.
This commit is contained in:
tegwick 2026-06-19 21:07:37 +02:00
parent 64d7c18c3f
commit 80648a78b7
6 changed files with 8 additions and 95 deletions

View file

@ -31,7 +31,7 @@ behaviour.
| `VERSION` | OpenBao image tag this overlay targets (`openbao-values.yaml`) | | `VERSION` | OpenBao image tag this overlay targets (`openbao-values.yaml`) |
| `presets.json` | Hidden login defaults (`netkingdom`, `platform-admin`, …) | | `presets.json` | Hidden login defaults (`netkingdom`, `platform-admin`, …) |
| `overlay.css` | Hide raw OpenBao login fields | | `overlay.css` | Hide raw OpenBao login fields |
| `overlay.js` | Apply presets, branding, mount deep-link | | `overlay.js` | Apply presets, branding, direct KeyCape OIDC sign-in |
| `nginx.conf` | Gateway proxy + HTML injection | | `nginx.conf` | Gateway proxy + HTML injection |
| `patches/<version>/manifest.sha256` | Upstream UI fingerprints for drift detection | | `patches/<version>/manifest.sha256` | Upstream UI fingerprints for drift detection |

View file

@ -49,7 +49,7 @@ http {
sub_filter_types text/html; sub_filter_types text/html;
sub_filter_once on; sub_filter_once on;
sub_filter '</head>' '<script src="/ui/platform-overlay/redirect-bootstrap.js"></script><link rel="stylesheet" href="/ui/platform-overlay/overlay.css"><script src="/ui/platform-overlay/overlay.js"></script></head>'; sub_filter '</head>' '<link rel="stylesheet" href="/ui/platform-overlay/overlay.css"><script src="/ui/platform-overlay/overlay.js" defer></script></head>';
} }
} }
} }

View file

@ -4,8 +4,6 @@
const PRESETS_URL = "/ui/platform-overlay/presets.json"; const PRESETS_URL = "/ui/platform-overlay/presets.json";
const MAX_APPLY_ATTEMPTS = 40; const MAX_APPLY_ATTEMPTS = 40;
const APPLY_INTERVAL_MS = 250; const APPLY_INTERVAL_MS = 250;
const MOUNT_WATCH_MS = 500;
const MOUNT_WATCH_MAX = 24;
const DEFAULT_PRESETS = { const DEFAULT_PRESETS = {
namespace: "", namespace: "",
method: "oidc", method: "oidc",
@ -20,7 +18,6 @@
let presets = { ...DEFAULT_PRESETS }; let presets = { ...DEFAULT_PRESETS };
let applyAttempts = 0; let applyAttempts = 0;
let applyTimer = null; let applyTimer = null;
let mountWatchTimer = null;
let overlayApplied = false; let overlayApplied = false;
let signInHandlerInstalled = false; let signInHandlerInstalled = false;
@ -32,38 +29,8 @@
); );
} }
function normalizedMount(value) { function isOidcCallbackPage() {
return (value || "").replace(/\/$/, ""); return window.location.pathname.includes("/oidc/");
}
function desiredMount() {
return normalizedMount(presets.mount || "netkingdom");
}
function currentMountFromQuery() {
return normalizedMount(
new URLSearchParams(window.location.search).get("with") || ""
);
}
function ensureAuthMountSelected() {
const mount = desiredMount();
const current = currentMountFromQuery();
if (current === mount || current === "keycape") {
return false;
}
if (!isAuthPage() || window.location.pathname.includes("/oidc/")) {
return false;
}
const params = new URLSearchParams(window.location.search);
params.set("with", `${mount}/`);
window.location.replace(
`${window.location.pathname}?${params.toString()}`
);
return true;
} }
function hideNode(node) { function hideNode(node) {
@ -121,7 +88,7 @@
document.addEventListener( document.addEventListener(
"click", "click",
(event) => { (event) => {
if (!isAuthPage()) return; if (!isAuthPage() || isOidcCallbackPage()) return;
const button = event.target.closest( const button = event.target.closest(
'#auth-submit, button[data-test="auth-submit"], form#auth-form button[type="submit"]' '#auth-submit, button[data-test="auth-submit"], form#auth-form button[type="submit"]'
@ -151,7 +118,7 @@
} }
function applyDom() { function applyDom() {
if (!isAuthPage() || overlayApplied) return false; if (!isAuthPage() || isOidcCallbackPage() || overlayApplied) return false;
hideNode(document.querySelector(".toolbar-namespace-picker")); hideNode(document.querySelector(".toolbar-namespace-picker"));
document document
@ -245,25 +212,6 @@
} }
} }
function stopMountWatch() {
if (mountWatchTimer !== null) {
window.clearInterval(mountWatchTimer);
mountWatchTimer = null;
}
}
function watchAuthMount() {
stopMountWatch();
let checks = 0;
mountWatchTimer = window.setInterval(() => {
checks += 1;
if (ensureAuthMountSelected() || checks >= MOUNT_WATCH_MAX) {
stopMountWatch();
}
}, MOUNT_WATCH_MS);
}
function scheduleApply() { function scheduleApply() {
stopApplyLoop(); stopApplyLoop();
applyAttempts = 0; applyAttempts = 0;
@ -292,15 +240,9 @@
} }
async function init() { async function init() {
if (!isAuthPage()) return; if (!isAuthPage() || isOidcCallbackPage()) return;
await loadPresets(); await loadPresets();
if (ensureAuthMountSelected()) {
return;
}
watchAuthMount();
installKeyCapeSignInHandler(); installKeyCapeSignInHandler();
if (document.readyState === "loading") { if (document.readyState === "loading") {

View file

@ -1,23 +0,0 @@
(function () {
"use strict";
var path = window.location.pathname;
if (path.indexOf("/oidc/") !== -1) {
return;
}
if (!/\/ui\/vault\/auth(?:\/|$)/.test(path) && !/\/ui\/?$/.test(path)) {
return;
}
var params = new URLSearchParams(window.location.search);
var current = (params.get("with") || "").replace(/\/$/, "");
if (current === "netkingdom" || current === "keycape") {
return;
}
params.set("with", "netkingdom/");
window.location.replace(
window.location.pathname + "?" + params.toString()
);
})();

View file

@ -27,7 +27,7 @@ if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
exit 0 exit 0
fi fi
for required in overlay.css overlay.js redirect-bootstrap.js presets.json nginx.conf VERSION; do for required in overlay.css overlay.js presets.json nginx.conf VERSION; do
if [ ! -f "$OVERLAY_DIR/$required" ]; then if [ ! -f "$OVERLAY_DIR/$required" ]; then
echo "missing overlay asset: $OVERLAY_DIR/$required" >&2 echo "missing overlay asset: $OVERLAY_DIR/$required" >&2
exit 1 exit 1
@ -47,7 +47,6 @@ $KUBECTL create configmap openbao-ui-overlay \
--namespace "$OPENBAO_NAMESPACE" \ --namespace "$OPENBAO_NAMESPACE" \
--from-file="$OVERLAY_DIR/overlay.css" \ --from-file="$OVERLAY_DIR/overlay.css" \
--from-file="$OVERLAY_DIR/overlay.js" \ --from-file="$OVERLAY_DIR/overlay.js" \
--from-file="$OVERLAY_DIR/redirect-bootstrap.js" \
--from-file="$OVERLAY_DIR/presets.json" \ --from-file="$OVERLAY_DIR/presets.json" \
--from-file="$OVERLAY_DIR/VERSION" \ --from-file="$OVERLAY_DIR/VERSION" \
--dry-run=client -o yaml | $KUBECTL apply -f - --dry-run=client -o yaml | $KUBECTL apply -f -

View file

@ -58,11 +58,6 @@ overlay_js="$(curl -fsS "$BASE_URL/ui/platform-overlay/overlay.js")"
overlay_css="$(curl -fsS "$BASE_URL/ui/platform-overlay/overlay.css")" overlay_css="$(curl -fsS "$BASE_URL/ui/platform-overlay/overlay.css")"
presets_json="$(curl -fsS "$BASE_URL/ui/platform-overlay/presets.json")" presets_json="$(curl -fsS "$BASE_URL/ui/platform-overlay/presets.json")"
require_pattern \
"index.html injects redirect bootstrap" \
"$index_html" \
'/ui/platform-overlay/redirect-bootstrap\.js'
require_pattern \ require_pattern \
"index.html injects overlay.js" \ "index.html injects overlay.js" \
"$index_html" \ "$index_html" \