Skip to content

prevent app refetch on token silent renew#1102

Open
ghazwarhili wants to merge 24 commits into
mainfrom
prevent-app-refetch-on-silent-renew
Open

prevent app refetch on token silent renew#1102
ghazwarhili wants to merge 24 commits into
mainfrom
prevent-app-refetch-on-silent-renew

Conversation

@ghazwarhili
Copy link
Copy Markdown
Contributor

PR Summary

  1. Emit token-free WebSocket URLs in useNotificationsUrlGenerator, stable across silent renews (depend on isAuthenticated, not on the token value).

  2. Pass getUserToken as getToken prop to NotificationsProvider so the fresh token is appended at each connection/reconnection.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR migrates user type references from User to Profile across announcement and top-bar components, adds a utility function to append auth tokens to URLs, and integrates token-based WebSocket authentication in the notifications provider.

Changes

User Profile Type Migration and WebSocket Token Authentication

Layer / File(s) Summary
Type and Import Updates
src/components/announcement/AnnouncementBanner.tsx, src/components/announcement/AnnouncementNotification.tsx, src/components/announcement/useGlobalAnnouncement.ts, src/components/topBar/TopBar.tsx, src/components/topBar/UserInformationDialog.tsx
Components import Profile type from oidc-client instead of User.
Component Prop Signatures
src/components/announcement/AnnouncementBanner.tsx, src/components/announcement/AnnouncementNotification.tsx, src/components/topBar/TopBar.tsx, src/components/topBar/UserInformationDialog.tsx
Props updated to accept userProfile?: Profile instead of user?: User or user: User | null; destructuring parameters renamed accordingly.
Hook and Logic Updates
src/components/announcement/useGlobalAnnouncement.ts, src/components/topBar/UserInformationDialog.tsx
Hook and useEffect conditions updated to check userProfile instead of user; fetches and role derivation reference userProfile and its nested fields; dependency arrays updated.
Token Utility Function
src/services/utils.ts
New appendToken(url: string) function retrieves current user token and appends it as a URL-encoded query parameter; returns undefined if no token exists.
WebSocket Token Integration
src/components/notifications/NotificationsProvider.tsx
WebSocket instantiation uses tokenized URL via appendToken(url) and flatMap to properly flatten connection instances; event handling and broadcast behavior preserved.
Tests and Assertions
src/components/topBar/tests/TopBar.test.tsx
Test props updated to pass userProfile object with identity claims instead of full user object.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'prevent app refetch on token silent renew' directly corresponds to the main objective of the PR: preventing unnecessary app refetches when the token is silently renewed, which is achieved by decoupling WebSocket URLs from token values.
Description check ✅ Passed The PR description is related to the changeset, clearly explaining the two key approaches: emitting token-free WebSocket URLs and passing getUserToken for fresh token retrieval at connection time.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/components/notifications/NotificationsProvider.tsx (1)

21-27: appendToken doesn't account for URL fragments.

If url ever contains a # fragment, appending ?access_token=... or &access_token=... after the fragment will make the token part of the fragment rather than the query string. Not an issue for current WebSocket URLs (which don't use fragments), but worth noting for robustness. A safer approach is to use URL/URLSearchParams, though that adds overhead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/notifications/NotificationsProvider.tsx` around lines 21 - 27,
appendToken currently appends the access_token after the entire URL, which
places it inside a fragment if the URL contains a '#' — fix appendToken to
preserve any fragment by splitting the URL at the '#' (or use the
URL/URLSearchParams API) so the query param is inserted into the main URL before
the fragment, then reattach the fragment; update the function appendToken to
detect and separate fragment, compute separator for the base part, append
encoded access_token to the base, and finally append '#' + fragment if present.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/components/notifications/NotificationsProvider.tsx`:
- Around line 21-27: appendToken currently appends the access_token after the
entire URL, which places it inside a fragment if the URL contains a '#' — fix
appendToken to preserve any fragment by splitting the URL at the '#' (or use the
URL/URLSearchParams API) so the query param is inserted into the main URL before
the fragment, then reattach the fragment; update the function appendToken to
detect and separate fragment, compute separator for the base part, append
encoded access_token to the base, and finally append '#' + fragment if present.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e8cf6099-21f6-4a92-839d-1981cb4bb51e

📥 Commits

Reviewing files that changed from the base of the PR and between 7df4d5b and 58a54fd.

📒 Files selected for processing (1)
  • src/components/notifications/NotificationsProvider.tsx

Copy link
Copy Markdown
Contributor

@flomillot flomillot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, I dont think it was necessary, but I let you check with the TL

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/announcement/useGlobalAnnouncement.ts (1)

26-47: ⚠️ Potential issue | 🟠 Major

Effect dependency is still too broad and can refetch on silent token renewal.

The userProfile object reference can change during OIDC token renewal even when user identity remains the same. The library recreates the Profile instance when merging updated claims. Depend on the stable sub claim instead to prevent unnecessary fetchCurrentAnnouncement() calls.

Suggested fix
-    useEffect(() => {
-        if (userProfile) {
+    useEffect(() => {
+        if (userProfile?.sub) {
             fetchCurrentAnnouncement()
                 .then((announcementDto) => {
@@
         } else {
             setAnnouncementInfos(undefined); // user disconnected
         }
-    }, [userProfile]);
+    }, [userProfile?.sub]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/announcement/useGlobalAnnouncement.ts` around lines 26 - 47,
The effect currently depends on the whole userProfile object so it refires on
silent OIDC token renewals; change the dependency to the stable user identifier
instead (use userProfile?.sub) so fetchCurrentAnnouncement() is only called when
the actual user changes—update the useEffect dependency array to depend on
userProfile?.sub and keep the same logic inside (fetchCurrentAnnouncement,
setAnnouncementInfos, error handling) while removing userProfile from the deps.
🧹 Nitpick comments (1)
src/components/announcement/AnnouncementBanner.tsx (1)

35-35: Tighten auth gating to avoid permissive “logged-in” checks.

userProfile?: Profile | {} combined with userProfile !== undefined can incorrectly allow truthy placeholder objects. Prefer a strict Profile prop and boolean truthiness check.

Suggested fix
-    userProfile?: Profile | {};
+    userProfile?: Profile;
@@
-        <Collapse in={userProfile !== undefined && visible} unmountOnExit sx={sx} style={{ margin: theme.spacing(1) }}>
+        <Collapse in={!!userProfile && visible} unmountOnExit sx={sx} style={{ margin: theme.spacing(1) }}>

Also applies to: 97-97

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/announcement/AnnouncementBanner.tsx` at line 35, The prop type
for AnnouncementBanner currently allows a permissive placeholder (userProfile?:
Profile | {}), which combined with checks like userProfile !== undefined can
treat empty objects as "logged-in"; change the prop to a strict optional Profile
(userProfile?: Profile) and update any truthiness checks in AnnouncementBanner
(and the other occurrence that checks userProfile !== undefined) to use explicit
existence checks such as if (userProfile) or if (userProfile != null) or
validate a specific Profile field (e.g., userProfile.id or userProfile.email)
before treating the user as authenticated so empty objects no longer pass the
gate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/notifications/NotificationsProvider.tsx`:
- Line 13: NotificationsProvider currently imports getUserToken and doesn't
expose the documented optional token-supplier API; update
NotificationsProviderProps to add an optional tokenSupplier (e.g. () =>
Promise<string> | string) and remove the hard dependency on getUserToken by
using the provided tokenSupplier where getUserToken is currently called
(references: NotificationsProviderProps, NotificationsProvider
function/component, and the places around the existing getUserToken usage at
lines noted in the review). For backward compatibility you may fallback to
calling getUserToken only when tokenSupplier is not provided, but ensure all
uses at the previously-importing sites (around the message fetch/auth code
paths) read the token via the new prop and types are updated accordingly.
- Around line 22-28: The code appends an access_token query param but
getUserToken() currently returns user.id_token; change the token source so
WebSocket auth uses the OAuth2 access token: update getUserToken (or its callers
in NotificationsProvider) to return user.access_token instead of user.id_token,
and update any places that build the socket URL (the initial connect and
reconnect logic that call appendToken) to pass that access token; ensure
appendToken continues to encode the token and that reconnect logic (the
reconnection call sites) uses the same getUserToken/access_token value.

In `@src/components/topBar/UserInformationDialog.tsx`:
- Around line 44-55: The dialog can display stale userDetails when switching
users or closing and reopening; update the component to clear userDetails
whenever the dialog is closed or the selected user changes by calling the state
setter (setUserDetails) when openDialog becomes false or when userProfile.sub
changes. Add a useEffect that watches [openDialog, userProfile?.sub] and calls
setUserDetails(null) if !openDialog or when userProfile?.sub is different, or
alternatively reset userDetails in the existing effect before calling
getUserDetails(userProfile.sub) to ensure old details are not shown. Ensure you
reference the existing userDetails and its setter (setUserDetails) and keep
getUserDetails usage intact.

---

Outside diff comments:
In `@src/components/announcement/useGlobalAnnouncement.ts`:
- Around line 26-47: The effect currently depends on the whole userProfile
object so it refires on silent OIDC token renewals; change the dependency to the
stable user identifier instead (use userProfile?.sub) so
fetchCurrentAnnouncement() is only called when the actual user changes—update
the useEffect dependency array to depend on userProfile?.sub and keep the same
logic inside (fetchCurrentAnnouncement, setAnnouncementInfos, error handling)
while removing userProfile from the deps.

---

Nitpick comments:
In `@src/components/announcement/AnnouncementBanner.tsx`:
- Line 35: The prop type for AnnouncementBanner currently allows a permissive
placeholder (userProfile?: Profile | {}), which combined with checks like
userProfile !== undefined can treat empty objects as "logged-in"; change the
prop to a strict optional Profile (userProfile?: Profile) and update any
truthiness checks in AnnouncementBanner (and the other occurrence that checks
userProfile !== undefined) to use explicit existence checks such as if
(userProfile) or if (userProfile != null) or validate a specific Profile field
(e.g., userProfile.id or userProfile.email) before treating the user as
authenticated so empty objects no longer pass the gate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 95aa6798-915d-4f68-ae61-cfb53e49d553

📥 Commits

Reviewing files that changed from the base of the PR and between 58a54fd and 896fdf7.

📒 Files selected for processing (7)
  • src/components/announcement/AnnouncementBanner.tsx
  • src/components/announcement/AnnouncementNotification.tsx
  • src/components/announcement/useGlobalAnnouncement.ts
  • src/components/notifications/NotificationsProvider.tsx
  • src/components/topBar/TopBar.tsx
  • src/components/topBar/UserInformationDialog.tsx
  • src/components/topBar/tests/TopBar.test.tsx

Comment thread src/components/notifications/NotificationsProvider.tsx
Comment thread src/components/notifications/NotificationsProvider.tsx Outdated
Comment thread src/components/topBar/UserInformationDialog.tsx
@ghazwarhili ghazwarhili requested a review from flomillot April 28, 2026 15:39
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/components/notifications/NotificationsProvider.tsx (1)

88-88: Consider removing connectionsRef from the dependency array.

Refs are stable across renders and don't need to be listed as effect dependencies. ESLint's react-hooks/exhaustive-deps rule typically exempts refs. Removing it clarifies intent: this effect reacts only to accessToken changes.

-    }, [accessToken, connectionsRef]);
+    }, [accessToken]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/notifications/NotificationsProvider.tsx` at line 88, The
useEffect in NotificationsProvider currently lists connectionsRef in its
dependency array but refs are stable and shouldn't be included; update the
effect that uses accessToken and connectionsRef so the dependency array contains
only accessToken (remove connectionsRef) and ensure any values from the ref are
accessed inside the effect body (no other unstable variables are omitted); this
clarifies intent in the NotificationsProvider component and satisfies
react-hooks expectations for useEffect.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/components/notifications/NotificationsProvider.tsx`:
- Line 88: The useEffect in NotificationsProvider currently lists connectionsRef
in its dependency array but refs are stable and shouldn't be included; update
the effect that uses accessToken and connectionsRef so the dependency array
contains only accessToken (remove connectionsRef) and ensure any values from the
ref are accessed inside the effect body (no other unstable variables are
omitted); this clarifies intent in the NotificationsProvider component and
satisfies react-hooks expectations for useEffect.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a58541de-9029-458c-bec7-d151a9d67c2a

📥 Commits

Reviewing files that changed from the base of the PR and between 896fdf7 and 469e63f.

📒 Files selected for processing (1)
  • src/components/notifications/NotificationsProvider.tsx

Comment thread src/components/notifications/NotificationsProvider.tsx
Comment thread src/components/notifications/NotificationsProvider.tsx Outdated
@ghazwarhili ghazwarhili requested a review from flomillot May 6, 2026 11:56
Comment thread src/components/topBar/UserInformationDialog.tsx Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/notifications/utils.ts`:
- Line 7: Update the getUserToken function in src/redux/commonStore.ts so it
returns the user's access token (user?.access_token) instead of the ID token
(user?.id_token); this ensures appendToken (used by appendToken in
src/components/notifications/utils.ts) supplies a proper access_token query
parameter for WebSocket auth—locate getUserToken and change its return value to
user?.access_token (and run any related unit/manual checks to confirm consumers
like appendToken still expect an access_token).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 36ed8928-e300-47ed-a728-2e8ef1e41564

📥 Commits

Reviewing files that changed from the base of the PR and between 469e63f and bb5f5ae.

📒 Files selected for processing (4)
  • src/components/announcement/AnnouncementBanner.tsx
  • src/components/notifications/NotificationsProvider.tsx
  • src/components/notifications/utils.ts
  • src/components/topBar/UserInformationDialog.tsx

Comment thread src/components/notifications/utils.ts Outdated
Comment thread src/components/topBar/UserInformationDialog.tsx Outdated
Comment thread src/components/notifications/NotificationsProvider.tsx Outdated
Comment thread src/components/announcement/useGlobalAnnouncement.ts Outdated
@ghazwarhili ghazwarhili requested a review from sBouzols May 6, 2026 16:28
const rws = new ReconnectingWebSocket(() => url, [], {
// this option set the minimum duration being connected before reset the retry count to 0
.flatMap(([urlKey, url]) => {
const urlWithToken = appendToken(url);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get token before and test only once if we have it ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@ghazwarhili ghazwarhili requested a review from jonenst May 13, 2026 13:06
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants