Skip to content

Conversation

@chirag-madlani
Copy link
Collaborator

@chirag-madlani chirag-madlani commented Dec 22, 2025

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.

Summary by Gitar

  • Local SSO testing infrastructure:
    • Docker-based Keycloak SAML and LDAP providers replace external cloud dependencies
    • Comprehensive setup scripts and documentation for local testing
  • E2E authentication tests:
    • 18 Playwright tests covering login/logout, token refresh/expiry, and multi-tab scenarios
    • SSO test utilities with JWT validation and token expiry helpers
  • CI/CD workflows:
    • New GitHub Actions workflows for automated SSO testing with local providers
    • Tests properly excluded from regular Playwright runs via config

This will update automatically on new commits.


@github-actions github-actions bot added safe to test Add this label to run secure Github workflows on PRs UI UI specific issues labels Dec 22, 2025
@chirag-madlani
Copy link
Collaborator Author

gitar fix ci

@gitar-bot
Copy link

gitar-bot bot commented Dec 23, 2025

gitar fix ci

I've checked the CI status for this PR and all checks are passing successfully:

✅ Java checkstyle
✅ Maven builds (MySQL and PostgreSQL)
✅ Python tests (3.10, 3.11)
✅ CodeQL analysis
✅ All other security and analysis checks

The skipped checks (playwright-ci-postgresql, py-checkstyle, ui-coverage-tests) are expected workflow skips for this PR type.

Could you clarify which specific CI check you'd like me to address? If you're seeing a different failure, please let me know which check is failing.

@chirag-madlani
Copy link
Collaborator Author

gitar fix this suggestion
Code Quality: Inconsistent token clearing - refresh token still uses setRefreshToken('')
📄 openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/AuthProvider.tsx:268

@gitar-bot
Copy link

gitar-bot bot commented Dec 23, 2025

gitar fix this suggestion
Code Quality: Inconsistent token clearing - refresh token still uses setRefreshToken('')
📄 openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/AuthProvider.tsx:268

Fixed! I've removed the redundant setRefreshToken('') call from resetUserDetails().

Since clearOidcToken() calls clearAppState() which removes the entire app state storage (including both OIDC and refresh tokens), the separate setRefreshToken('') call was unnecessary and inconsistent.

The token cleanup is now handled consistently by the single clearOidcToken() call.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 24, 2025

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 64%
64.76% (51476/79490) 42.46% (25168/59275) 45.94% (7943/17289)

@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 2, 2026

@gitar-bot
Copy link

gitar-bot bot commented Jan 5, 2026

Code Review 👍 Approved with suggestions

Comprehensive SSO testing infrastructure with excellent documentation. Two minor code quality issues identified.

Suggestions 💡 2 suggestions
Edge Case: Request listener added but never removed in SSO-002 test

📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Auth/SSOAuthentication.spec.ts:4667-4678

In test SSO-002, a request listener is added with page.on('request', ...) but it's never removed after the test. While Playwright handles cleanup between tests, it's good practice to remove listeners explicitly to avoid potential memory leaks or unexpected behavior if test execution is interrupted.

Suggested fix:

const requestHandler = (request: Request) => {
  if (request.url().includes('/api/v1/')) {
    const authHeader = request.headers()['authorization'];
    if (authHeader && authHeader !== 'Bearer null') {
      hasAuthToken = true;
    }
  }
};

page.on('request', requestHandler);
await page.waitForTimeout(2000);
page.off('request', requestHandler); // Clean up listener
expect(hasAuthToken).toBeFalsy();
Code Quality: JWT decoding uses atob which can fail on non-standard padding

📄 openmetadata-ui/src/main/resources/ui/playwright/utils/ssoAuthUtils.ts:6972-6975

The getJWTExpiry function uses atob() for Base64 decoding, which doesn't handle URL-safe Base64 (used in JWTs with - and _ instead of + and /) or missing padding. While JWTs typically use standard Base64, some providers may produce tokens that need URL-safe decoding.

Suggested fix:

export function getJWTExpiry(token: string): number | null {
  try {
    const parts = token.split('.');
    if (parts.length !== 3) {
      return null;
    }
    // Handle URL-safe Base64 and padding
    let payload = parts[1].replace(/-/g, '+').replace(/_/g, '/');
    while (payload.length % 4) {
      payload += '=';
    }
    const decoded = JSON.parse(atob(payload));
    return decoded.exp ? decoded.exp * 1000 : null;
  } catch {
    return null;
  }
}
Resolved ✅ 1 resolved
Code Quality: Inconsistent token clearing - refresh token still uses setRefreshToken('')

📄 openmetadata-ui/src/main/resources/ui/src/components/Auth/AuthProviders/AuthProvider.tsx:268
The change correctly introduces clearOidcToken() which uses removeItem to properly delete the token from storage. However, on the very next line, setRefreshToken('') still sets the refresh token to an empty string instead of removing it.

For consistency and proper storage cleanup, consider also adding a clearRefreshToken() function that removes the refresh token entry entirely, similar to how clearOidcToken() works.

Current behavior:

  • OIDC token: Removed from storage (correct)
  • Refresh token: Set to empty string (inconsistent)

This inconsistency could lead to:

  1. Stale empty string entries left in storage
  2. Confusion about the intended cleanup behavior

Suggested fix: Add a clearRefreshToken() function that mirrors clearOidcToken() and use it in resetUserDetails():

export const clearRefreshToken = async (): Promise<void> => {
  try {
    const state = await getAppState();
    state.refreshToken = undefined;
    await setAppState(state);
  } catch {
    // Storage failures are intentionally ignored...
  }
};

Then update resetUserDetails():

clearOidcToken();
clearRefreshToken();

What Works Well

Well-architected SSO testing infrastructure with local Docker-based providers (Keycloak SAML, LDAP) eliminating external dependencies. Excellent documentation including README, setup guides, and troubleshooting. The 18 comprehensive Playwright tests cover core flows, token refresh, multi-tab scenarios, and edge cases thoroughly. Clear separation of concerns between test helpers and test specs.

Rules 🎸 1 action taken

Gitar Rules

🎸 Summary Enhancement: Updated PR description with accurate SSO testing summary

2 rules not applicable. Show all rules by commenting gitar display:verbose.

Options

Auto-apply is off Gitar will not commit updates to this branch.
✅ Code review is on Gitar will review this change.
Display: compact Hiding non-applicable rules.

Comment with these commands to change:

Auto-apply ✅ Code review Compact
gitar auto-apply:on         
gitar code-review:off         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | This comment will update automatically (Docs)

@chirag-madlani chirag-madlani changed the title fix(ui): logout should clear all the stale state and clear tokens test(e2e): sso tests Jan 5, 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 To release Will cherry-pick this PR into the release branch UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants