EUREKA-72: Investigate options consortia UI bundles
- 1 Spike Overview
- 2 Background
- 3 Problem Statement
- 4 Scope
- 5 Proposed Solutions
- 5.1 Option 1: Custom JavaScript Functions with Login Form Customization
- 5.1.1 Overview
- 5.1.2 Sequence Diagram
- 5.1.3 Implementation Details
- 5.1.4 Pros
- 5.1.5 Cons
- 5.1.6 JavaScript functions example
- 5.1.7 Summary
- 5.2 Option 2: Keycloak Custom Authenticator for All Tenants
- 5.2.1 Overview
- 5.2.2 Sequence Diagram
- 5.2.3 Implementation Details
- 5.2.4 Pros
- 5.2.5 Cons
- 5.2.6 Authenticator implementation example
- 5.2.7 Summary
- 5.3 Option 3: Hybrid Approach with Simplified Custom Authenticator and JavaScript Redirection
- 5.3.1 Overview
- 5.3.2 Sequence Diagram
- 5.3.3 Implementation Details
- 5.3.4 Pros
- 5.3.5 Cons
- 5.3.6 JavaScript Code Example
- 5.3.7 Keycloak Custom Authenticator Example
- 5.3.8 Summary
- 5.4 Option 4: Custom Keycloak Authenticator (FolioEcsUsernamePasswordFormV2)
- 5.4.1 Overview
- 5.4.2 Sequence Diagram
- 5.4.3 Implementation Details
- 5.4.4 Pros
- 5.4.5 Cons
- 5.4.6 Keycloak Custom Authenticator Example
- 5.4.7 Summary
- 5.1 Option 1: Custom JavaScript Functions with Login Form Customization
- 6 Prerequisites
- 7 Conclusion
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:
Custom JavaScript Functions with Login Form Customization
Keycloak Custom Authenticator for All Tenants
Hybrid Approach with Simplified Custom Authenticator and JavaScript Redirection
Custom Keycloak Authenticator for the Central realm
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
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.
Retrieve User's Tenant
HTTP Request to
mod-login-keycloak
: The JavaScript code sends an HTTP POST request tomod-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.
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.
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-keycloak
extra 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
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.
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.
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.
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 implementation example
The authenticator implementation example can be found here:
https://github.com/folio-org/folio-keycloak-plugins/tree/feature/ecs-folio-authenticator/ecs-folio-authenticator
Summary
This option offers a secure, server-side solution that centralizes authentication logic within Keycloak, enhancing performance and scalability. However, significant development effort and careful maintenance are required to ensure compatibility with Keycloak updates and realm configurations.
Option 3: Hybrid Approach with Simplified Custom Authenticator and JavaScript Redirection
Overview
This hybrid option combines server-side tenant resolution with client-side redirection to implement Automatic Tenant Selection in FOLIO. It utilizes a simplified custom Keycloak Authenticator that only resolves the user's home tenant (realm) based on the provided username and does not handle credential validation or generate encrypted data. The Authenticator either authenticates the user if they belong to the current realm or redirects them to their home tenant's login page. Client-side JavaScript on the login page manages redirections transparently, providing a seamless user experience.
Sequence Diagram
Diagram Explanation
Actors and Participants:
Folio User: The end-user attempting to log in.
Browser: The user's web browser executing JavaScript and handling HTTP requests/responses.
Keycloak Consortia Realm (
kc_cr
): The central Keycloak realm with the simplified custom Authenticator configured.Keycloak Tenant Realm (
kc_tr
): The user's home tenant realm in Keycloak.
Flow Breakdown:
The user accesses the unified login page.
The browser displays the login page.
The user enters their credentials and submits the form.
JavaScript intercepts the form submission and sends an AJAX POST request with the username to the consortia realm (
kc_cr
).The simplified custom Authenticator in the consortia realm processes the username to determine the user's home tenant realm.
The Authenticator responds:
If the user belongs to the consortia realm, it proceeds with authentication.
If the user belongs to a different tenant realm, it responds with a redirect to the appropriate realm's login page.
JavaScript in the browser handles the redirect seamlessly by updating the form action and submitting the form to the tenant realm (
kc_tr
).The user is authenticated in their home tenant realm.
Upon successful authentication, the user is redirected to their FOLIO landing page.
Implementation Details
Client-Side JavaScript
Event Listener: Adds an event listener to intercept the login form submission.
Form Data Collection: Collects the username input by the user.
AJAX Request: Sends an asynchronous POST request to the consortia realm's login endpoint with the username.
Response Handling:
If the response indicates that the user belongs to the consortia realm, the JavaScript proceeds with the authentication flow.
If the response is a redirect to the tenant realm, the JavaScript updates the form action to the tenant realm's login endpoint and submits the form.
Simplified Custom Keycloak Authenticator (Server-Side)
Consortia Realm Authenticator:
Processes the username to determine the user's home tenant realm.
If the user belongs to the consortia realm:
Proceeds with the standard authentication process (validating credentials).
If the user belongs to a different tenant realm:
Responds with a redirect to the tenant realm's login page.
Tenant Realm Authentication:
The tenant realm handles authentication using its standard process.
No custom Authenticator is required in the tenant realm.
Security Measures
Server-Side Credential Handling: Credentials are only processed on the server side, minimizing exposure.
Reduced Client-Side Logic: JavaScript handles redirection without processing credentials.
Pros
Enhanced Security
Server-Side Credential Validation: Credentials are validated on the server side, reducing exposure risk.
No Credential Handling in JavaScript: Client-side code does not process or transmit credentials.
Improved User Experience
Seamless Redirection: JavaScript manages redirections transparently, providing a smooth login process.
Unified Login Screen: Users access a single login page without manual tenant selection.
Simplified Implementation
Simplified Authenticator: Reduces complexity by only resolving the tenant realm without handling credentials or encryption.
No Custom Data Encryption Needed: Eliminates the need for handling encrypted data between realms.
Flexibility
Centralized Tenant Resolution: Tenant determination logic is centralized in the consortia realm.
Ease of Updates: Changes to tenant resolution logic are confined to the simplified Authenticator.
Cons
CORS Configuration Requirement
Cross-Origin Resource Sharing (CORS): Must configure CORS between the FOLIO landing page and Keycloak login form to allow JavaScript redirection using
window.location.href = xhr.responseURL;
.Implications:
Security Considerations: Configuring CORS requires careful management to avoid exposing the application to cross-origin attacks.
Additional Complexity: Increases setup and maintenance overhead to ensure proper CORS policies are in place.
Browser Behavior: Inconsistent or incorrect CORS configuration may lead to login failures or inconsistent behavior across different browsers.
Development Effort
Custom Authenticator Development: Requires development and maintenance of the simplified Keycloak Authenticator.
JavaScript Maintenance: Client-side code needs to be maintained and tested across browsers.
Configuration Complexity
Realm Configuration: The consortia realm must be configured to use the simplified Authenticator.
Deployment Coordination: Synchronizing updates between server-side and client-side components.
Potential Error Handling Challenges
Redirection Failures: If JavaScript fails to handle redirects correctly, users may encounter login issues.
Fallback Mechanisms: Ensuring proper error messages and fallback options in case of authentication failures.
JavaScript Code Example
Keycloak Custom Authenticator Example
Summary
This hybrid approach leverages a simplified custom Authenticator in the consortia realm to resolve the user's home tenant based on the username. It does not handle credential validation or encrypted data transmission, reducing complexity while maintaining security. Client-side JavaScript manages redirections seamlessly without processing credentials, providing a unified and user-friendly login experience.
By centralizing tenant resolution and minimizing client-side logic, this option offers a secure and scalable solution for Automatic Tenant Selection in FOLIO. It balances implementation effort with the benefits of enhanced security and improved user experience.
Option 4: Custom Keycloak Authenticator (FolioEcsUsernamePasswordFormV2
)
Overview
This option involves developing a custom Keycloak Authenticator (FolioEcsUsernamePasswordFormV2
) that dynamically determines the realm to be used for user authentication based on the provided credentials. The Authenticator processes the authentication request within the current realm if the user belongs to it. If the user belongs to a different realm (linked through an Identity Provider), the Authenticator programmatically authenticates the user against that realm without redirecting the user or requiring any client-side JavaScript modifications.
Key Characteristics:
Server-Side Processing: All logic is handled on the server side within Keycloak.
No Login Form Customization: Does not require any changes to the login page or client-side JavaScript.
Enhanced Security: Prevents intruders from deducing user-realm associations, as no redirection or realm information is exposed to the client.
Seamless User Experience: Users experience a unified login process without manual tenant selection or noticeable redirections.
Sequence Diagram
Diagram Explanation
Actors and Participants:
Folio User: The end-user attempting to log in.
Browser: The user's web browser.
Keycloak with Custom Authenticator (
kc_custom
): Keycloak realm configured with theFolioEcsUsernamePasswordFormV2
Authenticator.Identity Provider Realm (
kc_idp
): The user's home tenant realm or external Identity Provider.
Flow Breakdown:
The user accesses the unified login page.
The browser displays the login page.
The user enters their credentials and submits the form.
The browser sends the authentication request to Keycloak (
kc_custom
).The custom Authenticator in Keycloak processes the credentials:
Identifies the realm associated with the user.
If the user belongs to the current realm, it proceeds with authentication.
If the user belongs to a linked realm or Identity Provider, it programmatically authenticates the user against that realm.
Upon successful authentication (either locally or against the Identity Provider), Keycloak returns the authentication response to the client.
The user is redirected to their FOLIO landing page.
Implementation Details
Custom Keycloak Authenticator (FolioEcsUsernamePasswordFormV2
)
Purpose: To determine the correct realm for user authentication and handle the authentication process accordingly without exposing realm information to the client.
Functionality:
Realm Identification: Based on the username provided, the Authenticator checks if the user exists in the current realm or is associated with a federated Identity Provider.
Local Authentication: If the user belongs to the current realm, it proceeds with standard password validation.
Programmatic Authentication Against Linked Realm:
If the user is linked to an Identity Provider, the Authenticator programmatically performs authentication against that Identity Provider using the provided credentials.
Utilizes the OAuth 2.0 Resource Owner Password Credentials Grant to obtain an access token from the Identity Provider.
Determines authentication success based on the response from the Identity Provider.
Security Measures:
Server-Side Credential Handling: Credentials are only handled within the Keycloak server environment.
No Exposure of Realm Information: Does not redirect the user or expose any realm-specific URLs or data to the client.
Brute-Force Protection: By not revealing user-realm associations, it prevents attackers from inferring relationships and targeting specific realms.
Key Components of the Authenticator Code:
Action Method:
Intercepts the authentication flow and retrieves the user based on the provided username.
Checks for federated identities associated with the user.
Password Validation:
If the user is linked to a federated Identity Provider, it performs programmatic authentication against that provider.
Otherwise, it proceeds with standard password validation.
Programmatic Authentication Against OIDC Identity Provider:
Constructs a token request to the Identity Provider's token endpoint.
Includes client credentials, username, and password in the request.
Parses the response to determine if authentication was successful.
Keycloak Configuration:
Authenticator Setup:
The custom Authenticator (
FolioEcsUsernamePasswordFormV2
) must be deployed to the Keycloak server.Configure the authentication flow to include the custom Authenticator.
Identity Providers Configuration:
Identity Providers (other realms) must be set up in Keycloak with appropriate client credentials.
Ensure that the Identity Providers allow authentication using the Resource Owner Password Credentials Grant.
Pros
Enhanced Security
No Realm Information Exposure: Prevents intruders from discovering user-realm associations, as no redirection or realm hints are provided to the client.
Server-Side Credential Handling: Credentials are processed entirely on the server side, reducing the risk of interception.
Brute-Force Protection: Limits the ability of attackers to target specific realms or users.
Simplified User Experience
Unified Login Process: Users access a single login page without manual tenant selection or noticeable redirections.
Seamless Authentication: The authentication process is transparent to the user, regardless of their home realm.
No Client-Side Modifications Required
No JavaScript Customization: Eliminates the need for custom client-side scripts or modifications to the login form.
Reduced Maintenance Overhead: Simplifies maintenance by avoiding browser compatibility issues or client-side code updates.
Centralized Logic
Single Point of Authentication Logic: All authentication decisions and processes are centralized within the custom Authenticator.
Ease of Updates: Changes to authentication logic are confined to the server-side code.
Cons
Development Complexity
Custom Authenticator Development: Requires in-depth knowledge of Keycloak's authentication mechanisms and custom Authenticator development.
Programmatic Authentication: Implementing programmatic authentication against other realms or Identity Providers adds complexity.
Identity Provider Compatibility
Support for Resource Owner Password Credentials Grant:
The linked Identity Providers must support the OAuth 2.0 Resource Owner Password Credentials Grant.
This grant type is deprecated in OAuth 2.1 and may not be supported or recommended in all environments.
Maintenance Overhead
Keycloak Updates: The custom Authenticator must be maintained and tested with new Keycloak releases to ensure compatibility.
Identity Provider Configuration: Changes in Identity Provider Configuration may require updates to the Authenticator.
Keycloak Custom Authenticator Example
Summary
This option offers a secure, server-side solution that centralizes authentication logic within a custom Keycloak Authenticator. By programmatically authenticating users against their home realms without exposing realm information or modifying the client-side login form, it enhances security and provides a seamless user experience.
Key Benefits:
Security: Prevents exposure of realm associations and handles credentials entirely on the server side.
User Experience: Provides a unified login process without manual tenant selection or redirections.
No Client-Side Changes: Avoids the need for custom JavaScript or login form modifications.
Considerations:
Development Effort: Requires custom Authenticator development and maintenance.
Identity Provider Requirements: Linked Identity Providers must support specific authentication grants.
Maintenance: Must ensure compatibility with Keycloak updates and manage Identity Provider configurations.
This custom Authenticator approach effectively addresses the challenges of Automatic Tenant Selection in FOLIO by securely determining the appropriate realm for authentication and processing the authentication request without exposing sensitive information to the client. It provides a robust and secure solution that maintains a seamless user experience, making it a strong candidate for implementation.
Prerequisites
Before implementing any of the proposed options for Automatic Tenant Selection in FOLIO, several prerequisites must be completed to ensure seamless integration, security, and functionality. These prerequisites involve configuring Keycloak realms, setting up identity providers, linking users across realms, and configuring authentication flows. Below are the detailed steps and the modules responsible for implementing them.
1. Keycloak Identity Provider Configuration
Purpose: To enable the Central realm to recognize and authenticate users from non-Central (institutional) tenant realms.
Action: When a tenant is added to the Consortium, an Identity Provider must be created in the Keycloak realm representing the Central tenant. This Identity Provider should point to the Keycloak realm that represents the non-Central tenant being added.
Implementation Module:
mgr-tenants
Details:
The
mgr-tenants
module, responsible for tenant management, should automate the creation of Identity Providers in the Central realm whenever a new tenant is added to the Consortium.This setup allows the Central realm to delegate authentication to the appropriate tenant realm based on the user's home institution.
2. Linking Keycloak Users Across Realms
Purpose: To ensure that shadow users in the Central realm are properly linked to their corresponding users in the non-Central tenant realms for seamless authentication and authorization.
Action: When a new user is created in a non-Central tenant, a shadow user is created in the Central tenant to represent the permissions assigned to this user in the Consortium context. The Keycloak users in both realms must be linked via an Identity Provider Link.
Implementation Module:
mod-users-keycloak
Details:
Keycloak users are created in both the Central and non-Central realms with the same user ID but are not inherently linked.
The
mod-users-keycloak
module should handle the creation of an Identity Provider Link for theshadow
user in the Central realm, linking it to the corresponding user in the non-Central realm.This linkage is essential for the custom Authenticators to programmatically authenticate users across realms without exposing realm details to the client.
3. Custom Authentication Flow Configuration
Purpose: To enable Keycloak realms to utilize custom Authenticators necessary for Automatic Tenant Selection.
Action: Configure a Custom Authentication Flow in Keycloak realms to incorporate the custom Authenticators developed for the chosen option.
Options and Configuration Requirements:
Option 2: Every realm (both Central and non-Central tenant realms) must have the Custom Authentication Flow preconfigured.
Options 3 and 4: Only the Central realm requires the Custom Authentication Flow to be preconfigured.
Implementation Module:
mgr-tenants
Details:
The
mgr-tenants
module should automate the configuration of the Custom Authentication Flow when:A Central realm is created.
A tenant (non-Central realm) is added to the Consortium.
This configuration ensures that the custom Authenticators are correctly integrated into the authentication processes of the relevant realms.
Proper setup of the authentication flow is critical for the custom Authenticators to function as intended, handling tenant resolution and authentication without manual intervention.
4. Adjustments for Cross-Origin Resource Sharing (CORS) - Option 3 Only
Purpose: To allow secure cross-origin requests between the FOLIO UI and Keycloak, which is necessary for client-side redirection handling in Option 3.
Action: Adjust the FOLIO UI bundle to support CORS requests between the FOLIO UI Landing Page and the Keycloak Login Form.
Implementation Module: FOLIO UI Bundle (Frontend)
Details:
Configure the FOLIO UI server to include appropriate CORS headers, allowing the browser to perform cross-origin AJAX requests required for the JavaScript redirection logic.
Ensure that the CORS policies are securely configured to prevent cross-origin attacks, specifying allowed origins, methods, and headers.
This adjustment is crucial for Option 3, where client-side JavaScript intercepts and handles authentication redirections.
Summary of Implementation Responsibilities
mgr-tenants
Module:Automate the creation of Identity Providers in the Consortium realm for each non-Consortium tenant added.
Configure Custom Authentication Flows in relevant Keycloak realms during realm creation or tenant addition.
mod-users-keycloak
Module:Link Keycloak users across realms by creating Identity Provider Links when shadow users are created in the Consortium realm.
FOLIO UI Bundle:
Adjust CORS settings to enable secure cross-origin requests between the FOLIO UI and Keycloak (Option 3 only).
Conclusion
After evaluating the four proposed options for implementing Automatic Tenant Selection in FOLIO, we have compiled a comparative analysis to aid in selecting the most suitable approach. Each option offers distinct advantages and challenges in terms of security, user experience, implementation complexity, maintenance, and scalability.
Comparative Analysis
Aspect | Option 1: Custom JavaScript Functions with Login Form Customization | Option 2: Keycloak Custom Authenticator for All Tenants | Option 3: Hybrid Approach with Simplified Custom Authenticator and JavaScript Redirection | Option 4: Custom Keycloak Authenticator ( |
---|---|---|---|---|
Security |
|
|
|
|
User Experience |
|
|
|
|
Implementation Effort |
|
|
|
|
Maintenance |
|
|
|
|
Scalability |
|
|
|
|
Complexity |
|
|
|
|
Recommendations
Option 1: Custom JavaScript Functions with Login Form Customization
While this option offers ease of implementation and a unified login experience, it poses significant security risks due to client-side handling of user credentials and the need to expose unauthorized APIs in mod-login-keycloak
. The reliance on client-side scripting makes it vulnerable to manipulation and interception, which is unacceptable for an authentication system.
Option 2: Keycloak Custom Authenticator for All Tenants
This option provides enhanced security through server-side processing and centralized authentication logic. However, it requires extensive development effort and complex configuration across all tenant realms. The need to maintain custom Authenticators with Keycloak updates adds to the maintenance overhead. While secure and scalable, the complexity and configuration requirements may be prohibitive.
Option 3: Hybrid Approach with Simplified Custom Authenticator and JavaScript Redirection
The hybrid option strikes a balance between security and implementation complexity. By centralizing tenant resolution in a simplified custom Authenticator and managing redirections via client-side JavaScript, it enhances security over Option 1 while reducing the development effort compared to Option 2. However, it introduces the need for CORS configuration between the FOLIO landing page and the Keycloak login forms, adding complexity and potential security concerns.
Option 4: Custom Keycloak Authenticator (FolioEcsUsernamePasswordFormV2
)
This option offers the highest level of security by handling all authentication logic server-side within a custom Keycloak Authenticator. It eliminates the need for client-side modifications, thereby reducing maintenance overhead and eliminating client-side vulnerabilities. Users experience a seamless and unified login process without exposure to realm information or redirections. While it requires in-depth Keycloak expertise and careful development, it minimizes security risks and is scalable across multiple tenants.
Final Recommendation
After careful consideration, Option 4: Custom Keycloak Authenticator (FolioEcsUsernamePasswordFormV2
) is the recommended solution for implementing Automatic Tenant Selection in FOLIO. This option provides the following key advantages:
Security: Maximizes security by ensuring all credentials and authentication logic are handled server-side, eliminating client-side vulnerabilities and exposure of realm information.
User Experience: Offers a seamless and transparent login process without requiring users to select their tenant or experience noticeable redirections.
Maintenance: Simplifies maintenance by centralizing authentication logic within the server-side Authenticator, avoiding the need to maintain client-side scripts or handle browser compatibility issues.
Scalability: Efficiently scales with the addition of new tenants, as the authentication logic remains centralized and does not require client-side updates.
Compliance: Avoids the use of deprecated authentication grants by utilizing supported and secure methods for programmatic authentication.
Considerations for Implementation:
Development Effort: While Option 4 requires custom development and in-depth knowledge of Keycloak's authentication mechanisms, the long-term benefits in security and maintenance justify the initial investment.
Identity Provider Compatibility: Ensure that linked Identity Providers support the required authentication methods and that appropriate configurations are in place (we already enable required configurations in the Keycloak realms: the Resource Owner Password Credentials grant).
Testing and Validation: Conduct thorough testing to verify the Authenticator's functionality across different scenarios and ensure compatibility with Keycloak updates.
Alternative Option:
If the development resources or expertise required for Option 4 are not currently available, Option 3: Hybrid Approach with Simplified Custom Authenticator and JavaScript Redirection serves as a viable interim solution. It enhances security over Option 1 and reduces complexity compared to Option 2. However, the CORS configuration and potential security implications should be carefully managed.
By adopting Option 4, FOLIO can enhance its authentication mechanism to provide a secure, seamless, and scalable solution for Automatic Tenant Selection, significantly improving the user experience across consortia institutions.