UX-913: silently refresh embedded auth on stale tabs#2328
UX-913: silently refresh embedded auth on stale tabs#2328malinskibeniamin wants to merge 1 commit intomasterfrom
Conversation
| </TransportProvider> | ||
| </ChakraProvider> | ||
| </CustomFeatureFlagProvider> | ||
| <TokenRefreshInterceptorProvider value={tokenRefreshInterceptor}> |
There was a problem hiding this comment.
module federation v1 vs v2. token refresh interceptor provider needs to work in both
| * Focus and visibility events usually arrive in a burst, so this hook debounces | ||
| * them and also deduplicates in-flight work. | ||
| */ | ||
| export const useEmbeddedAuthPrewarm = ({ |
There was a problem hiding this comment.
seems overkill
4a6c72a to
9f0bf8e
Compare
9f0bf8e to
94f7e19
Compare
|
@claude review, make sure this works for both module federation v1 and v2 |
|
Claude finished @malinskibeniamin's task in 3m 0s —— View job Review: UX-913 Silent Auth Refresh (MF v1 & v2)
Architecture: How v1 vs v2 DifferThe two paths use fundamentally different refresh strategies, which is correct given their different host contracts:
This asymmetry is intentional per the PR description, and both paths are coherent within their own contracts. Issues Found1.
On unmount, the interceptor is cleared ( In practice 2. MF v1 refresh contract is implicit and untested For v1 the entire "silent refresh" story depends on the host providing a // embedded-app.tsx:96-97
const defaultFetch = useMemo(() => window.fetch.bind(window), []);
const configuredFetch = p.fetch ?? defaultFetch;If no The embedded-app test only asserts the custom fetch is wired — it doesn't cover the fallback case. 3. In const token = refreshedToken || getAccessToken();
const token = refreshedToken ?? getAccessToken();4. Addressing the self-review comment at The 5. Addressing the self-review comment at The dual guard (
They cover different timing windows. The concern is valid if Minor Notes
SummaryThe core architecture works correctly for both MF v1 and v2. The main concerns are: the implicit contract that MF v1 hosts must provide a refresh-capable |
|
|
||
| function EmbeddedApp({ basePath = '', ...p }: EmbeddedProps) { | ||
| const tokenRefreshInterceptor = getRegisteredTokenRefreshInterceptor(); | ||
| const defaultFetch = useMemo(() => window.fetch.bind(window), []); |
There was a problem hiding this comment.
Could we please provide more comments on how these fetch mechanism works across apps? It was never clear to me and it's a bit confusing.
What
fetchpath so MF v1 hosts can recover stale bearer tokens through their existing authenticated fetchTokenManagerrefresh handling into setup-created clients, router/root transports, AI Gateway transports, and controlplane transportsfocus/visibilitychangeso stale tabs refresh before refetches surface rendering errorsWhy
When an embedded Console tab sits stale long enough for its bearer token to expire, coming back to it can trigger unauthenticated failures and confusing frontend stack traces. This change makes stale-tab recovery silent when possible and falls back to the existing embedded re-auth handoff when it is not.
How
createTokenRefreshInterceptor()into a shared utility and distribute it through a small context/registry layerTokenManager.refresh()and register/provide it anywhere embedded Connect transports are createdconfig.fetchso host-provided authenticated fetch implementations can refresh/retry requestsconsole:auth-errorAcceptance Criteria