Skip to end of banner
Go to start of banner

EUREKA-72: Investigate options consortia UI bundles

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Current »

Spike Overview

https://folio-org.atlassian.net/browse/EUREKA-72

Objective: To determine an approach for implementing Automatic Tenant Selection in FOLIO, allowing users to log into their home tenant without being prompted to select it manually, thereby enhancing the user experience across consortia institutions.

Background

FOLIO is a collaborative, open-source library services platform that enables multiple institutions within a consortium to use the same application. Each institution is represented as a separate tenant within FOLIO, and staff users are defined within their institution's tenant context. Users have capabilities assigned to them that define the actions they can perform within their tenant.

Currently, if a user from Institution A (Tenant A) needs to perform actions in Institution B (Tenant B), a shadow user is created in Tenant B with the necessary capabilities. The user must switch affiliations within the FOLIO application to change the tenant context for their session.

Keycloak is used as the Identity and Access Management (IAM) system for FOLIO, with each tenant represented as a separate Realm. Real FOLIO users correspond to Keycloak users with credentials, allowing them to authenticate and log in. Shadow users in FOLIO correspond to Keycloak users without credentials and cannot be used for login operations. Capabilities assigned in FOLIO are reflected as permissions granted to Keycloak users.

The current FOLIO implementation includes:

  • Single UI Bundle: Users log into a central tenant and switch affiliations as needed.

  • Manual Tenant Selection: Users select their tenant from a drop-down menu and are directed to the appropriate UI bundle for their tenant, authenticating in the Keycloak Realm associated with their tenant.

The need has arisen for an Automatic Tenant Selection feature where users are not prompted to select their tenant. Instead, the system detects the user's home tenant upon login and directs them accordingly.

Problem Statement

The spike aims to address the challenge of implementing Automatic Tenant Selection in FOLIO. The goal is to enable users to see a unified login screen and, upon authentication, be automatically directed to their home tenant without manual selection. This requires a method to detect the user's home tenant based on the user’s credentials and adjust the authentication flow accordingly within Keycloak and FOLIO.

Scope

In Scope

  • Investigate methods to automatically detect a user's home tenant during the login process.

  • Explore configurations or extensions in Keycloak to support automatic tenant selection based on user credentials.

  • Assess how automatic tenant selection affects authentication flow, session management, and capability assignments in FOLIO.

  • Ensure the proposed solution aligns with FOLIO's architecture and maintains security and compliance standards.

Out of Scope

  • Implementation or deployment of the automatic tenant selection feature.

  • Modifications to existing tenant switching mechanisms or shadow user management.

  • User interface design changes beyond the login screen.

Proposed Solutions

Two possible options have been identified to implement Automatic Tenant Selection in FOLIO:

  1. Custom JavaScript Functions with Login Form Customization

  2. Keycloak Custom Authenticator for All Tenants

Each option is analyzed in detail below, including high-level sequence diagrams, implementation details, and the pros and cons.

Option 1: Custom JavaScript Functions with Login Form Customization

Overview

This option involves customizing the Keycloak login form using JavaScript to determine the correct tenant (realm) based on the user's input (username). The process includes intercepting the login request, retrieving the user's tenant information by communicating with mod-login-keycloak, and then redirecting the user to authenticate against the appropriate tenant realm.

Sequence Diagram

The high-level sequence diagram for this option is as follows:

Implementation Details

  1. Customize Keycloak Login Page

    • JavaScript Injection: Modify the Keycloak login page to include custom JavaScript code that executes when the user submits their credentials.

    • Intercept Submission: The JavaScript code intercepts the form submission event to prevent the default behavior.

  2. Retrieve User's Tenant

    • HTTP Request to mod-login-keycloak: The JavaScript code sends an HTTP POST request to mod-login-keycloak, passing the entered username and password.

    • Authentication Check: mod-login-keycloak communicates with Keycloak to validate the user's credentials.

    • Tenant Resolution: Upon successful validation, mod-login-keycloak determines the user's home tenant.

  3. Redirect to Tenant's Login Page

    • Construct Tenant URL: The JavaScript code constructs the URL for the tenant's login page based on the tenant information received.

    • Redirection: The JavaScript function requests the tenant-specific login page. It does not render it for the user but sends the authentication Post request to Keycloak.

  4. Authenticate Against Tenant Realm

    • Submit Credentials: The user's credentials are submitted to the tenant realm's for authentication.

    • Validation: Keycloak validates the credentials within the tenant realm.

    • Authentication Success: Upon successful authentication, the user is redirected to the FOLIO landing page.

Pros

  • User Experience

    • Unified Login Screen: Users access a single login screen without the need to select their tenant manually.

    • Seamless Redirection: Redirection to the tenant realm happens transparently to the user.

  • Implementation Simplicity

    • Minimal Backend Changes: The logic is handled primarily on the client side through JavaScript.

    • No Custom Authenticator Required: Avoids the complexity of developing and maintaining a custom Keycloak authenticator.

  • Flexibility

    • Easy Updates: Changes to tenant resolution logic can be applied by updating the JavaScript code.

Cons

  • Security Concerns

    • Credential Exposure Risk: User credentials are handled in the browser and sent over HTTP to mod-login-keycloak before authentication, increasing the risk of interception.

    • Client-Side Vulnerabilities: JavaScript code can be manipulated or disabled by users or malicious actors.

    • Man-in-the-Middle Attacks: Increased risk if HTTPS is not strictly enforced.

    • mod-login-keycloak has to expose unathorized API that can be used for hacking

  • Maintenance Overhead

    • Browser Compatibility: Ensuring the JavaScript functions correctly across all browsers and devices.

    • Debugging Difficulty: Client-side issues can be harder to trace and resolve.

    • mod-login-keycloakextra complexity: mod-login-keycloak must be improved to handle credentials validation and realm resolution.

  • Reliance on Client-Side Logic

    • User Manipulation: Technically savvy users could alter the JavaScript to change the authentication flow.

    • Accessibility Issues: Users with JavaScript disabled or using assistive technologies may encounter problems.

  • Complex Error Handling

    • User Feedback: Providing meaningful error messages is more complex when multiple steps are involved client-side.

JavaScript functions example

function get_realm_link_by_username() {
    const username = document.getElementById("username").value;

    // Determine which link to return based on the username content
    // This is just a stub. The HTTP call to mod-login-keycloak must be done here instead.
    if (username.includes("coltest")) {
        const link = document.getElementById("social-college");
        return link ? link.href : null;
    } else if (username.includes("unitest")) {
        const link = document.getElementById("social-university");
        return link ? link.href : null;
    }

    // Return null if no matching link is found
    return null;
}
async function process_complex_realm_login() {
    const href = get_realm_link_by_username();

    if (!href) {
        console.error("No matching realm link found for username.");
        return;
    }

    try {
        // Perform a GET request to the resolved href
        const response = await fetch(href);

        // Check if the response is OK (status code 200-299)
        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
        }

        // Parse the response as text
        const result = await response.text();

        // Create a new DOM parser to convert the HTML string to a document object
        const parser = new DOMParser();
        const doc = parser.parseFromString(result, "text/html");

        // Extract the action attribute from the form in the parsed document
        const fetchedFormAction = doc.querySelector("#kc-form-login")?.action;

        // Check if the action was found and apply it to the current form, then submit
        if (fetchedFormAction) {
            const currentForm = document.getElementById("kc-form-login");
            currentForm.action = fetchedFormAction;  // Set the current form's action
            currentForm.method = "post";  // Set the current form's method to POST.

            // Submit the form programmatically
            currentForm.submit();
        } else {
            console.error("Form action not found in the fetched content.");
        }
    } catch (error) {
        // Log any errors to the console
        console.error("Error fetching login link:", error);
    }
}

Summary

While this option offers a quick way to implement Automatic Tenant Selection with minimal backend changes, it introduces significant security risks and maintenance challenges due to its reliance on client-side scripting and handling of user credentials in the browser.

Option 2: Keycloak Custom Authenticator for All Tenants

Overview

This option involves developing a custom Keycloak Authenticator (e.g., FolioAuthenticator) and configuring Keycloak to use this authenticator across all realms configured for consortia and institutional tenants. The custom authenticator handles tenant detection and authentication flow server-side, enhancing security and centralizing the logic.

Sequence Diagram

The high-level sequence diagram for this option is as follows:

Implementation Details

  1. Develop Custom Authenticator (FolioAuthenticator)

    • Server-Side Logic: Implement the authenticator using Keycloak's Service Provider Interface (SPI).

    • Tenant Detection: Incorporate logic to determine the user's home tenant based on the username or other identifiers and configured identity providers.

    • Encrypted Data Handling: Prepare and handle encrypted custom data containing credentials and timestamp for secure transmission between realms.

  2. Configure Keycloak Realms

    • Consortia Realm: Apply the FolioAuthenticator to the central consortia realm.

    • Institutional Realms: Apply the same authenticator to each institutional tenant realm.

    • Authentication Flow: Modify the authentication flow in Keycloak to include the custom authenticator.

  3. Authentication Flow

    • Initial Login Request: User submits credentials to the consortia realm.

    • Tenant Resolution: The custom authenticator checks if the username exists and retrieves the user's identity provider (tenant realm).

    • Redirect Handling: If the user's identity provider is found, the authenticator prepares encrypted custom data and redirects the user to the tenant realm's login page.

    • Fallback Mechanism: If the identity provider is not found, proceed with default authentication in the consortia realm.

  4. Tenant Realm Authentication

    • Data Decryption: The tenant realm's custom authenticator decrypts the received custom data.

    • Credential Validation: The tenant realm validates the user's credentials.

    • Authentication Success: User is authenticated and redirected to the FOLIO landing page.

Pros

  • Enhanced Security

    • Server-Side Credential Handling: Credentials are processed within Keycloak servers, reducing exposure.

    • Encrypted Data Transmission: Sensitive information is encrypted when transmitted between realms.

    • Reduced Attack Surface: Less reliance on client-side scripting minimizes vulnerabilities.

  • Centralized Logic

    • Consistency Across Realms: The custom authenticator standardizes authentication flow for all tenants.

    • Easier Maintenance: Updates to authentication logic are centralized.

  • Improved Performance

    • Streamlined Authentication: Fewer external calls and redirections improve login speed.

    • Scalable Solution: Better suited for handling a large number of tenants.

  • User Experience

    • Seamless Login Flow: Users experience a smooth login process without unnecessary redirects or prompts.

    • Fallback Authentication: Supports default authentication if tenant detection fails.

Cons

  • Development Complexity

    • Custom Authenticator Development: Requires in-depth knowledge of Keycloak's SPI and authentication mechanisms.

    • Testing and Validation: Extensive testing is needed to ensure reliability across different scenarios.

  • Maintenance Overhead

    • Version Compatibility: The custom authenticator must be maintained with Keycloak updates.

    • Configuration Management: All realms must be correctly configured to use the custom authenticator. This configuration must be made transparently during the Consortia configuration. (mgr-tenants? mod-consortia-keycloak? which one should be responsible for that?)

  • Deployment Challenges

    • Rollout Strategy: Deploying changes across multiple realms requires careful planning.

    • Error Handling Complexity: Properly managing authentication errors across realms can be complex.

  • Potential Single Point of Failure

    • Authenticator Dependency: Issues with the custom authenticator could affect authentication for all users.

Authenticator implemenation example

The authenticator implementation example can be foulnd here:
https://github.com/folio-org/folio-keycloak-plugins/tree/feature/ecs-folio-authenticator/ecs-folio-authenticator

Keycloak Authentication flow configuration

TODO:

Summary

This option offers a secure, server-side solution that centralizes authentication logic within Keycloak, enhancing performance and scalability. However, it requires significant development effort and careful maintenance to ensure compatibility with Keycloak updates and realm configurations.

Conclusion

Both options aim to implement Automatic Tenant Selection in FOLIO to enhance the user experience. Here's a comparative analysis:

Aspect

Option 1: Custom JavaScript Functions

Option 2: Keycloak Custom Authenticator

Security

Potential vulnerabilities due to client-side credential handling

Enhanced security with server-side processing

User Experience

Unified login but may face delays and security warnings

Seamless and secure login experience

Implementation

Easier initial setup, minimal backend changes

Requires custom development and in-depth Keycloak expertise

Maintenance

Potential issues with browser compatibility and JavaScript updates

Centralized logic simplifies maintenance across all realms

Scalability

May become unwieldy as the number of tenants increases

Better suited for scaling with multiple tenants

Complexity

Simpler to implement but riskier in terms of security

More complex but offers a robust, secure solution

  • No labels