Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions ui/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# The image serves static files only: the Dockerfile copies index.html,
# silent-callback.html and dist/, and nothing else is needed at build time.
#
# Without this file the whole ui/ tree is sent to the daemon as build context -
# node_modules alone dwarfs everything the image actually contains, which makes a
# three-COPY build take minutes.
#
# Allowlist rather than denylist: adding a COPY without extending this list fails
# the build instead of silently depending on whatever happens to be lying around.
*
!index.html
!silent-callback.html
!dist
Comment thread
hu-ahmed marked this conversation as resolved.

# Source maps are only produced by `npm start` (esbuild serve); keep stale ones left in a
# local dist/ out of locally built images.
dist/**/*.map
1 change: 1 addition & 0 deletions ui/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ FROM nginxinc/nginx-unprivileged:alpine
WORKDIR /usr/share/nginx/html

COPY ./index.html .
COPY ./silent-callback.html .
COPY ./dist ./dist
2 changes: 1 addition & 1 deletion ui/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as esbuild from 'esbuild';
import {sassPlugin} from 'esbuild-sass-plugin';

const config = {
entryPoints: ['main.ts'],
entryPoints: ['main.ts', 'silent-callback.ts'],
bundle: true,
outdir: 'dist',
loader: {
Expand Down
24 changes: 1 addition & 23 deletions ui/silent-callback.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,6 @@
<title>Silent Refresh Callback</title>
</head>
<body>
<script>
try {
import('oidc-client-ts').then(({ UserManager }) => {
const userManager = new UserManager();

userManager.signinSilentCallback()
.then(() => {
if (window.opener) {
window.close();
}
})
.catch(error => {
console.error('Silent refresh callback failed:', error);
});
}).catch(error => {
console.error('Failed to load oidc-client-ts:', error);
});
} catch (error) {
console.error('Silent callback error:', error);
}
</script>
<script type="module" src="./dist/silent-callback.js"></script>
</body>
</html>


44 changes: 44 additions & 0 deletions ui/silent-callback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2026 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
import { UserManager, UserManagerSettings } from 'oidc-client-ts';

/*
* Entry point for silent-callback.html, the page oidc-client-ts loads in a hidden iframe as
* `silent_redirect_uri` when renewing an access token without a refresh token.
*
* The page's only job is to hand the response URL back to the parent frame;
* `signinSilentCallback()` delegates to IFrameNavigator.callback(), which reads nothing from
* the settings except the optional `iframeNotifyParentOrigin` (defaulting to this page's own
* origin). Hence the placeholder settings below: `authority`, `client_id` and `redirect_uri` are
* required by UserManagerSettings but are never touched on this path.
*
* Because the settings are hard-coded, a provider's configured `iframeNotifyParentOrigin` is not
* applied here, so this page only works when served from the same origin as the UI itself (as
* the Docker image does). A `silent_redirect_uri` on a different origin is not supported.
*
* Passing an object at all is what matters - `new UserManager()` throws, because
* UserManagerSettingsStore dereferences `args.redirect_uri` before any defaulting.
*/
const callbackOnlySettings: UserManagerSettings = {
Comment thread
hu-ahmed marked this conversation as resolved.
authority: '',
client_id: '',
redirect_uri: '',
};
Comment thread
hu-ahmed marked this conversation as resolved.

new UserManager(callbackOnlySettings)
.signinSilentCallback()
.catch((error) => {
// Nothing is recoverable from inside the iframe: oidc-client-ts times the silent
// request out and raises a SilentRenewError on the UserManager that started it.
console.error('Silent refresh callback failed:', error);
});
2 changes: 1 addition & 1 deletion ui/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
// TypeScript 6.0 no longer auto-includes all of node_modules/@types
"types": ["jest"]
},
"include": ["main.ts", "./custom.d.ts", "./modules/**/*", "__tests__/utils"]
"include": ["main.ts", "silent-callback.ts", "./custom.d.ts", "./modules/**/*", "__tests__/utils"]
}
Loading