Conversation
silent-callback.html has never worked in any environment. It was added by c2eda4f "support silent token refresh" together with the OIDC wiring in authorization.ts, but the packaging half was never done, and the page had two further defects that only a real browser would surface: 1. It never reaches the image. ui/Dockerfile copies only ./index.html and ./dist; the page sits at ui/ root, so it is copied by neither. Confirmed in a running eclipse/ditto-ui container - the web root holds index.html, 50x.html and dist/{main.css,main.js}, and a filesystem-wide search for *callback* returns nothing. 2. build.mjs could not have supplied it either. It has a single entry point (main.ts), and its `.html` loader is `text`, which inlines HTML imported from TypeScript rather than emitting standalone HTML. Nothing imported the page, so `COPY ./dist` had nothing to pick up. 3. The page could not run even if served. It did `import('oidc-client-ts')` - a bare ESM specifier, unresolvable without an import map, and the page had none. It also called `new UserManager()` with no argument, which throws: UserManagerSettingsStore dereferences `args.redirect_uri` before any defaulting. The only reference to the page anywhere is the environmentTemplates.json default, http://localhost:8000/silent-callback.html - the esbuild dev server, whose `servedir: '.'` made the file reachable during local development and masked all of the above. Fix all three: move the script into silent-callback.ts and add it to entryPoints so esbuild resolves and bundles oidc-client-ts, point the page at ./dist/silent-callback.js the way index.html points at ./dist/main.js, and copy the page in the Dockerfile. The placeholder settings in silent-callback.ts are deliberate. signinSilentCallback() delegates to IFrameNavigator.callback(), which reads nothing from the settings but the optional iframeNotifyParentOrigin; authority and client_id are required by UserManagerSettings yet never touched on this path. Passing an object at all is what avoids the constructor throw. Verified end to end: * `npm run build` (tsc -noEmit && node build.mjs) passes and emits dist/silent-callback.js (65 kB). * The bundle carries the real contract - the "oidc-client" message source, postMessage and keepOpen are all present - with 0 dynamic imports and 0 unresolved bare specifiers left. * Building ui/Dockerfile and serving the image returns 200 for both /silent-callback.html (text/html) and /dist/silent-callback.js (application/javascript), alongside the existing index.html and main.js. Note the renewal path itself is only exercised when no refresh token is present: UserManager.signinSilent() returns from its refresh-token branch whenever `user?.refresh_token` is set, so a client requesting offline_access never loads this page. That is why the breakage went unnoticed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tree
The image serves three things - index.html, silent-callback.html and dist/ -
but with no .dockerignore the entire ui/ tree was sent to the daemon as build
context, node_modules included. A three-COPY build took minutes.
Allowlist rather than denylist, so adding a COPY without extending this list
fails the build instead of silently depending on whatever happens to be lying
around in the working tree.
Build time drops from minutes to ~10s, and the image is byte-for-byte the same
set of files: 50x.html, index.html, silent-callback.html and dist/{main.css,
main.css.map, main.js, main.js.map, silent-callback.js} at identical sizes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
ui/silent-callback.htmlhas never worked in any environment. It was added by c2eda4f "support silent token refresh" alongside the OIDC wiring inauthorization.ts, but the packaging half was never done — and the page carried two further defects that only a real browser would surface.1. It never reaches the image.
ui/Dockerfilecopies only./index.htmland./dist; the page sits atui/root, so it is copied by neither. Confirmed inside a runningeclipse/ditto-uicontainer rather than inferred: the web root holdsindex.html,50x.htmlanddist/{main.css,main.js}, and a filesystem-wide search for*callback*returns nothing.2.
build.mjscould not have supplied it either. It has a single entry point (main.ts), and its.htmlloader istext— which inlines HTML imported from TypeScript as a string rather than emitting standalone HTML files. Nothing imports the page, soCOPY ./disthad nothing to pick up.3. The page could not run even if served. It did:
'oidc-client-ts'is a bare ESM specifier — unresolvable without an import map, and the page has none. Andnew UserManager()with no argument throws:UserManagerSettingsStoredereferencesargs.redirect_uribefore any defaulting.Why it went unnoticed. The only reference to the page anywhere is the
environmentTemplates.jsondefault,http://localhost:8000/silent-callback.html— the esbuild dev server, whoseservedir: '.'made the file reachable during local development and masked all three problems. Beyond that,UserManager.signinSilent()returns from its refresh-token branch wheneveruser?.refresh_tokenis set:so any client requesting
offline_accessnever loads this page at all.Fix
ui/silent-callback.ts(new) — the script becomes a real entry point, so esbuild resolves and bundlesoidc-client-tsinstead of leaving a bare specifier.ui/build.mjs—entryPoints: ['main.ts', 'silent-callback.ts'].ui/silent-callback.html— loads./dist/silent-callback.js, mirroring howindex.htmlloads./dist/main.js.ui/Dockerfile—COPY ./silent-callback.html .The placeholder settings in
silent-callback.tsare deliberate and commented:signinSilentCallback()delegates toIFrameNavigator.callback(), which reads nothing from the settings but the optionaliframeNotifyParentOrigin(defaulting to the page's own origin).authorityandclient_idare required byUserManagerSettingsbut never touched on this path — and passing an object at all is what avoids the constructor throw.Also included:
ui/.dockerignoreWith no
.dockerignore, the wholeui/tree went to the daemon as build context —node_modulesincluded — so a three-COPYbuild took minutes. An allowlist was chosen over a denylist so that adding aCOPYwithout extending the list fails the build rather than silently depending on whatever is lying around in the working tree.Build time drops from minutes to ~10s, and the image contains a byte-for-byte identical set of files.
Verification
npm run build(tsc -noEmit && node build.mjs) passes, emittingdist/silent-callback.js(65 kB)."oidc-client"message source,postMessageandkeepOpenare all present — with 0 dynamic imports and 0 unresolved bare specifiers.ui/Dockerfileand serving the image:/silent-callback.htmltext/html/dist/silent-callback.jsapplication/javascript/index.htmltext/html/dist/main.jsapplication/javascript.dockerignore:50x.html,index.html,silent-callback.html,dist/{main.css, main.css.map, main.js, main.js.map, silent-callback.js}at the same sizes.Not verified
The renewal round trip itself needs a browser session with an IdP that issues no refresh token, waiting for an access token to approach expiry — I could not exercise that. What is verified is that the page and its bundle are served correctly and that the bundled code contains the message contract
AbstractChildWindowvalidates.