feat: IBM ams proxy based login#1169
Draft
edwinjosechittilappilly wants to merge 19 commits intomainfrom
Draft
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
.env.exampleandsrc/config/settings.pyfiles, including toggles and cookie/header names. [1] [2]src/auth/ibm_auth.py, supporting both signature-less decoding (trusted by Traefik) and full RS256 validation when required._get_ibm_userinsrc/dependencies.pyto authenticate users via IBM credentials header, IBM JWT cookie, or local dev fallback, and persist credentials for background tasks.Frontend Authentication Flow Updates
frontend/contexts/auth-context.tsxto support IBM auth mode, including detection, login, and logout logic, as well as a newloginWithIbmmethod. The login page and redirect logic were updated accordingly. [1] [2] [3] [4] [5] [6] [7] [8]Backend Authentication and Session Handling
/api/auth/logoutendpoint insrc/api/auth.pyto handle IBM session cookies, providing partial logout warnings when full session termination requires action in IBM Watsonx Data./api/auth/ibm/loginendpoint for local development, storing Basic credentials in a cookie for subsequent authentication.Credential Persistence and Management
upsert_ibm_credentialsmethod to the connection manager for storing/updating IBM credentials per user for background tasks and connector operations.Other Improvements and Refactoring
These changes collectively enable robust IBM AMS authentication support, seamless user experience across environments, and secure credential handling throughout the stack.