Skip to content

Keycloak UI Customization and Frontend Route Protection

Date: 2025-04-21 Participants: AI Assistant, Rakesh Gangwar

Context

Following the initial Keycloak integration (Phase 1), the standard Keycloak login page redirect felt disconnected from the application's UI (built with shadcn-svelte). There was also a need to protect frontend routes, ensuring only authenticated users could access certain parts of the application.

Discussion & Decisions

  1. Custom Login Page vs. Theming:

    • Initially explored creating a fully custom login form within the Svelte application using shadcn components (/login route, LoginForm.svelte).
    • This approach required collecting username/password directly, implying the use of the Resource Owner Password Credentials (ROPC) grant type in Keycloak.
    • Recognized the security risks associated with ROPC (application handling passwords) and decided against it.
    • Decision: Opted to use the standard OIDC redirect flow but customize Keycloak's login page appearance using Keycloak Theming to match the application's shadcn look and feel.
  2. Keycloak Theme Implementation:

    • Created a new theme directory: keycloak/themes/shadcn-theme/.
    • Configured theme.properties to inherit from the base Keycloak theme and include custom CSS.
    • Added placeholder CSS (custom-shadcn.css) with initial styles.
    • Created a keycloak/Dockerfile to build a custom Keycloak image containing the shadcn-theme.
    • Modified backend/docker-compose.yml to build and use this custom Keycloak image instead of the official one.
    • Iteratively refined custom-shadcn.css by adding specific selectors and !important flags to:
      • Hide the default Keycloak logo (#kc-logo, #kc-logo-wrapper, #kc-header, #kc-header-wrapper).
      • Remove the default background image and set a plain background color (html, body, .login-pf-page, etc.).
      • Vertically center the login card using Flexbox on the page container.
  3. Frontend Route Protection:

    • Decision: Implement route protection within SvelteKit's layout system.
    • Created frontend/src/routes/+layout.ts.
    • Added a load function that runs in the browser.
    • The load function checks the authentication status using the user store from authService.ts.
    • If the user is not authenticated (!$user) and the requested route is not in a predefined publicRoutes list (/, /login, /callback, etc.), it throws a redirect(307, '/login').
  4. UI Enhancements & Fixes:

    • Refactored AuthStatus.svelte to use shadcn-svelte components (Button, Avatar, DropdownMenu) for a more integrated look.
    • Conditionally rendered the AppSidebar in frontend/src/routes/+layout.svelte based on the $user store, hiding it for unauthenticated users.
    • Resolved several Svelte 5 / TypeScript / shadcn-svelte integration issues:
      • Used onclick prop instead of on:click directive for event handling on some shadcn components.
      • Removed problematic asChild and builders props from DropdownMenu.Trigger when used with a nested Button.
      • Removed comments within component tags that were causing Svelte parser errors.
  5. Authentication UI Improvements:

    • Decision: Improved the authentication UI to better integrate with the overall interface.
    • Modified AuthStatus.svelte to only show the login button on the root page when logged out.
    • Positioned the login button on the right side of the "Last Updated" message in the header.
    • Made "Last Updated" message, SidebarTrigger, and Separator only visible when the user is logged in.
    • Removed the logout functionality from the header and exclusively used the logout button in the sidebar navigation (nav-user.svelte).
    • Updated app-sidebar.svelte to use the actual user data from the auth service instead of mock data.
    • Created a derived store in app-sidebar.svelte that formats the user data to be compatible with the NavUser component.
    • Removed redundant AuthStatus components from the layout to avoid duplication.

Next Steps

  1. Continue refining the CSS in keycloak/themes/shadcn-theme/login/resources/css/custom-shadcn.css to fully match the application's shadcn theme (fonts, colors, spacing, input styles, card styles, etc.).
  2. Thoroughly test route protection across different scenarios (direct navigation, refresh, login/logout).
  3. Consider adding a custom logo to the Keycloak theme.
  4. Implement a loading state for authentication to improve user experience during login/logout operations.

References

  • Keycloak Theming Documentation
  • docs/logs/devlogs/2025-04-21-keycloak-implementation-strategy.md
  • docs/logs/devlogs/2025-04-21-keycloak-phase1-implementation.md