Skip to content

chore(ui): ensure token updated before making failed req#27140

Merged
chirag-madlani merged 1 commit intomainfrom
fix-loop-401-req
Apr 8, 2026
Merged

chore(ui): ensure token updated before making failed req#27140
chirag-madlani merged 1 commit intomainfrom
fix-loop-401-req

Conversation

@chirag-madlani
Copy link
Copy Markdown
Collaborator

This pull request improves the reliability of token refresh and request retry logic in the authentication flow. The main focus is to ensure that Axios interceptors are fully initialized before retrying requests and that token persistence is properly handled after a refresh.

Authentication and Token Refresh Improvements:

  • Made the initializeAxiosInterceptors call asynchronous and awaited its completion before retrying pending requests in AuthProvider.tsx, ensuring interceptors are ready before requests are retried.
  • Introduced a new private method waitForTokenPersistence in TokenServiceUtil.ts to wait until the refreshed token is actually persisted, improving reliability in token handling.
  • Refactored token variable naming for clarity in the token refresh logic (oldToken instead of token) in TokenServiceUtil.ts.

Describe your changes:

Fixes

I worked on ... because ...

Type of change:

  • Bug fix
  • Improvement
  • New feature
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.

Copilot AI review requested due to automatic review settings April 7, 2026 18:51
@chirag-madlani chirag-madlani requested a review from a team as a code owner April 7, 2026 18:51
@github-actions github-actions bot added safe to test Add this label to run secure Github workflows on PRs UI UI specific issues labels Apr 7, 2026
@gitar-bot
Copy link
Copy Markdown

gitar-bot bot commented Apr 7, 2026

Code Review ✅ Approved

Ensures the authentication token is refreshed before retrying failed requests in the UI, preventing unnecessary 401 errors. No issues found.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to harden the UI authentication flow by improving token refresh reliability and the retry of failed (401) requests, primarily by ensuring Axios interceptors are initialized before replaying queued requests and by adding logic intended to wait for refreshed token persistence.

Changes:

  • Await initializeAxiosInterceptors() before retrying queued Axios requests after a token refresh.
  • Rename the pre-refresh token variable to oldToken for clarity in TokenService.
  • Add a waitForTokenPersistence helper (currently unused) intended to wait until the refreshed token is actually persisted.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
openmetadata-ui/src/main/resources/ui/src/utils/Auth/TokenService/TokenServiceUtil.ts Adds a token-persistence wait helper and refines token naming in refresh logic.
openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/AuthProvider.tsx Ensures interceptor initialization is awaited before retrying queued requests after refresh.
Comments suppressed due to low confidence (1)

openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/AuthProvider.tsx:524

  • On the success path the queue is retried and then cleared, but in the failure paths (token falsy or refreshToken() rejects) the queued promises are not rejected and pendingRequests is not cleared. That can leave the original Axios call hanging and can leak queued configs. Consider rejecting all queued requests and clearing pendingRequests when refresh fails / logout is triggered.
                      await initializeAxiosInterceptors();
                      pendingRequests.forEach(({ resolve, reject, config }) => {
                        axiosClient.request(config).then(resolve).catch(reject);
                      });

Comment on lines +164 to +177
private async waitForTokenPersistence(oldToken: string) {
const maxAttempts = 20;
const delayMs = 50;

for (let attempt = 0; attempt < maxAttempts; attempt++) {
await new Promise((resolve) => setTimeout(resolve, delayMs));

const currentToken = await getOidcToken();

if (currentToken && currentToken !== oldToken) {
return;
}
}
}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

waitForTokenPersistence is introduced but never called. As a result, the refresh flow still relies on the existing fixed delay and does not actually wait for the refreshed token to be persisted (as described in the PR). Either wire this into refreshToken() (e.g., using the captured oldToken) or remove the unused method. Also consider returning a boolean / throwing on timeout so callers can handle the persistence not completing instead of silently continuing after max attempts.

Copilot uses AI. Check for mistakes.
Comment on lines +517 to 521
.then(async (token) => {
if (token) {
// Retry the pending requests
initializeAxiosInterceptors();
await initializeAxiosInterceptors();
pendingRequests.forEach(({ resolve, reject, config }) => {
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

The retry path treats a falsy refreshToken() result as a refresh failure (resetUserDetails(true)), but some authenticators intentionally return void for silent refresh (e.g., OidcAuthenticator’s renewIdToken resolves with no token and persists it via the silent-callback). In those cases this branch will force-logout and will never retry queued requests even though the token may have been refreshed. Consider basing the decision to retry on the persisted token (e.g., re-read getOidcToken() / compare against the previous token) or adjust TokenService.refreshToken() to resolve with the persisted token once it’s available.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 64%
64.27% (59500/92568) 43.77% (31019/70854) 46.94% (9356/19931)

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 7, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

🟡 Playwright Results — all passed (24 flaky)

✅ 3594 passed · ❌ 0 failed · 🟡 24 flaky · ⏭️ 207 skipped

Shard Passed Failed Flaky Skipped
🟡 Shard 1 452 0 5 2
🟡 Shard 2 638 0 4 32
🟡 Shard 3 648 0 3 26
🟡 Shard 4 617 0 5 47
🟡 Shard 5 605 0 2 67
🟡 Shard 6 634 0 5 33
🟡 24 flaky test(s) (passed on retry)
  • Features/CustomizeDetailPage.spec.ts › Database Schema - customization should work (shard 1, 1 retry)
  • Flow/Metric.spec.ts › Verify Related Metrics Update (shard 1, 1 retry)
  • Flow/Tour.spec.ts › Tour should work from help section (shard 1, 1 retry)
  • Flow/Tour.spec.ts › Tour should work from URL directly (shard 1, 1 retry)
  • Pages/UserCreationWithPersona.spec.ts › Create user with persona and verify on profile (shard 1, 1 retry)
  • Features/BulkEditEntity.spec.ts › Glossary (shard 2, 1 retry)
  • Features/DataQuality/BundleSuiteBulkOperations.spec.ts › Bulk selection operations (shard 2, 1 retry)
  • Features/DomainTierCertificationVoting.spec.ts › DataProduct - Certification assign, update, and remove (shard 2, 1 retry)
  • Features/ExploreQuickFilters.spec.ts › search dropdown should work properly for quick filters (shard 2, 1 retry)
  • Features/Permissions/GlossaryPermissions.spec.ts › Team-based permissions work correctly (shard 3, 1 retry)
  • Features/TestSuiteMultiPipeline.spec.ts › TestSuite multi pipeline support (shard 3, 1 retry)
  • Flow/ExploreDiscovery.spec.ts › Should display deleted assets when showDeleted is checked and deleted is not present in queryFilter (shard 3, 1 retry)
  • Pages/Customproperties-part2.spec.ts › entityReferenceList shows item count, scrollable list, no expand toggle (shard 4, 1 retry)
  • Pages/DescriptionVisibility.spec.ts › Customized Table detail page Description widget shows long description (shard 4, 1 retry)
  • Pages/Domains.spec.ts › Rename domain with deeply nested subdomains (3+ levels) verifies FQN propagation (shard 4, 1 retry)
  • Pages/Domains.spec.ts › Rename domain with data products attached at domain and subdomain levels (shard 4, 1 retry)
  • Pages/Domains.spec.ts › Verify Domain entity API calls do not include invalid domains field in glossary term assets (shard 4, 1 retry)
  • Pages/ExploreTree.spec.ts › Verify Database and Database Schema available in explore tree (shard 5, 1 retry)
  • Pages/Glossary.spec.ts › Add and Remove Assets (shard 5, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › Column lineage for apiEndpoint -> searchIndex (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage schema filter selection (shard 6, 1 retry)
  • Pages/ProfilerConfigurationPage.spec.ts › Non admin user (shard 6, 1 retry)
  • Pages/ServiceEntity.spec.ts › Announcement create, edit & delete (shard 6, 1 retry)
  • Pages/Users.spec.ts › Permissions for table details page for Data Consumer (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

@chirag-madlani chirag-madlani merged commit 5cdf7fa into main Apr 8, 2026
52 checks passed
@chirag-madlani chirag-madlani deleted the fix-loop-401-req branch April 8, 2026 04:49
chirag-madlani added a commit that referenced this pull request Apr 8, 2026
chirag-madlani added a commit that referenced this pull request Apr 8, 2026
SaaiAravindhRaja pushed a commit to SaaiAravindhRaja/OpenMetadata that referenced this pull request Apr 12, 2026
SaaiAravindhRaja pushed a commit to SaaiAravindhRaja/OpenMetadata that referenced this pull request Apr 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants