Skip to content

feat: IBM ams proxy based login#1169

Draft
edwinjosechittilappilly wants to merge 19 commits intomainfrom
IBM_AMS_NO_LOGIN
Draft

feat: IBM ams proxy based login#1169
edwinjosechittilappilly wants to merge 19 commits intomainfrom
IBM_AMS_NO_LOGIN

Conversation

@edwinjosechittilappilly
Copy link
Collaborator

This pull request introduces comprehensive support for IBM AMS (Watsonx Data embedded mode) authentication, enabling the application to authenticate users using IBM credentials and JWTs in addition to the existing Google OAuth and no-auth modes. The changes include new backend authentication logic, frontend context and login flow updates, and configuration/environment variable additions. The implementation ensures compatibility with both production (Traefik-proxied) and local development environments and manages session and credential handling accordingly.

IBM AMS Authentication Support

  • Added new environment variables and configuration options to enable IBM authentication via the .env.example and src/config/settings.py files, including toggles and cookie/header names. [1] [2]
  • Implemented IBM JWT decoding and validation helpers in src/auth/ibm_auth.py, supporting both signature-less decoding (trusted by Traefik) and full RS256 validation when required.
  • Added a new dependency _get_ibm_user in src/dependencies.py to authenticate users via IBM credentials header, IBM JWT cookie, or local dev fallback, and persist credentials for background tasks.

Frontend Authentication Flow Updates

  • Enhanced the authentication context in frontend/contexts/auth-context.tsx to support IBM auth mode, including detection, login, and logout logic, as well as a new loginWithIbm method. The login page and redirect logic were updated accordingly. [1] [2] [3] [4] [5] [6] [7] [8]

Backend Authentication and Session Handling

  • Updated the /api/auth/logout endpoint in src/api/auth.py to handle IBM session cookies, providing partial logout warnings when full session termination requires action in IBM Watsonx Data.
  • Added a new /api/auth/ibm/login endpoint for local development, storing Basic credentials in a cookie for subsequent authentication.
  • Modified the OpenSearch client creation logic to accept either Bearer or Basic tokens, supporting IBM credential passthrough.

Credential Persistence and Management

  • Added an upsert_ibm_credentials method to the connection manager for storing/updating IBM credentials per user for background tasks and connector operations.

Other Improvements and Refactoring

  • Ensured no-auth mode is disabled when IBM auth is enabled, and improved logging and error handling throughout the authentication flow. [1] [2] [3]

These changes collectively enable robust IBM AMS authentication support, seamless user experience across environments, and secure credential handling throughout the stack.

edwinjosechittilappilly and others added 19 commits March 10, 2026 02:32
Introduce support for IBM Watsonx Data (AMS) embedded authentication via the ibm-lh-console-session cookie. Add IBM_AUTH_ENABLED and IBM_JWT_PUBLIC_KEY_URL settings and .env.example entries; pre-fetch and cache IBM JWT public key at startup. Implement JWT validation and key rotation handling in new auth.ibm_auth module. Wire IBM auth into dependencies (extract/validate cookie, set request.state.user), main service initialization, auth_service (prevent Google OAuth login when IBM auth is active and expose ibm_auth_mode in user info), and session_manager (use IBM JWT as-is). Update frontend auth context and login page to recognize IBM auth mode and disable local login/logout and redirect accordingly. Adjust logout endpoint to no-op when IBM auth is enabled.
Update IBM public key fetching to expect a JSON payload with a "public_key" field instead of using raw response content. Adds validation and logging when the key is missing, encodes the key if returned as a string, and continues to cache the loaded PEM public key. Raises a ValueError on missing key to surface the error earlier.
init_oauth() raises ValueError when IBM auth mode is enabled, but /auth/init currently catches all exceptions and returns HTTP 500. This makes a normal “login not supported in IBM mode” case look like a server error. Prefer raising an HTTPException(status_code=400/409, ...) here, or update auth_init to translate ValueError into a 4xx response.
create_user_opensearch_client() now calls jwt_token.startswith(...), which will raise if jwt_token is None. There are existing call sites that pass jwt_token=None (e.g., API key auth / internal tasks), and while SessionManager.get_effective_jwt_token() often fills this in, it can still return None for unknown users. Consider handling None explicitly (e.g., raise a clear error or default to Bearer wrapping only when jwt_token is a non-empty string) to avoid an unexpected AttributeError.
decode_ibm_jwt() only catches jwt.DecodeError, but expired tokens (and many other invalid token conditions) raise ExpiredSignatureError / InvalidTokenError and will currently bubble up, likely turning a normal “not authenticated” case into a 500. Consider catching jwt.InvalidTokenError (or jwt.PyJWTError) and returning None consistently.
When IBM_AUTH_ENABLED, return a "partial_logout" response that clears IBM-related browser cookies but warns that the server-side IBM/AMS session may still be active and should be terminated via the identity provider. The default "logged_out" response is now returned only when IBM auth is not enabled. Also added a comment about not requiring secure=True for local development when setting the "ibm-auth-basic" cookie in ibm_login.
Add support for Traefik/AMS header-based IBM authentication and persist per-user Basic credentials.

- Frontend: remove the IBM username/password form and ensure login redirect also considers IBM auth mode.
- Config: add IBM_CREDENTIALS_HEADER setting (default X-IBM-LH-Credentials).
- Connectors: add ConnectionManager.upsert_ibm_credentials to store/update ibm_credentials connector entries in connections.json.
- Dependencies: make _get_ibm_user async and handle a configurable credentials header (decode Basic token, derive username, persist credentials via connector_service), then short-circuit and return a constructed User; update get_current_user and get_optional_user to await the IBM auth helper.
- Session manager / User model: add opensearch_username and opensearch_credentials fields; when IBM auth is enabled, always create a fresh OpenSearch client (do not reuse cached client) to handle per-request rotating credentials.

These changes enable production deployments where Traefik injects IBM credentials, allow background processes to reuse those credentials, and align session/client behavior for IBM AMS auth.

  Backend:
  - src/config/settings.py — Added IBM_CREDENTIALS_HEADER = os.getenv("IBM_CREDENTIALS_HEADER", "X-IBM-LH-Credentials")
  - src/session_manager.py — Added opensearch_username and opensearch_credentials fields to User; updated get_user_opensearch_client to skip the cache in IBM mode so credential rotation is always reflected
  - src/connectors/connection_manager.py — Added upsert_ibm_credentials() async method to store/update per-user IBM credentials in connections.json with connector_type="ibm_credentials"
  - src/dependencies.py — Made _get_ibm_user, get_current_user, get_optional_user all async; added Option 0 (highest priority) that reads the configurable IBM_CREDENTIALS_HEADER, decodes the base64 credentials, persists to
  connections.json, and sets jwt_token to "Basic <b64>" so OpenSearch gets the right Authorization header

  Frontend:
  - frontend/app/login/page.tsx — Removed IbmLoginForm component; added isIbmAuthMode to both the redirect useEffect and early-return guard so IBM users are immediately bounced to /chat without seeing any login form
Add handling for IBM Basic credentials and propagate them into Langflow/MCP global variables. Introduces extract_ibm_credentials() in auth/ibm_auth.py to decode "Basic <b64>" strings and reuse decoded username/password. dependencies.py now uses this helper and stores opensearch_username/opensearch_credentials on the User when present. Pass jwt_token through ChatService and LangflowFileService to add_provider_credentials_to_headers, which now accepts jwt_token and builds IBM OpenSearch vars via build_ibm_opensearch_vars(). build_mcp_global_vars_from_config also accepts jwt_token and injects OPENSEARCH_USERNAME, OPENSEARCH_PASSWORD and JWT when IBM_AUTH_ENABLED and a Basic credential is provided. This enables Langflow and MCP components to authenticate OpenSearch in IBM deployments.
@github-actions github-actions bot added frontend 🟨 Issues related to the UI/UX backend 🔷 Issues related to backend services (OpenSearch, Langflow, APIs) enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Mar 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend 🔷 Issues related to backend services (OpenSearch, Langflow, APIs) enhancement 🔵 New feature or request frontend 🟨 Issues related to the UI/UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants