[PR #24599] [CLOSED] feat(ntid): propagate AMD NTID to LLM Gateway via user HTTP header #82609

Closed
opened 2026-05-13 17:09:08 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/24599
Author: @datar-ai
Created: 5/12/2026
Status: Closed

Base: mainHead: feat/ntid-user-header-propagation


📝 Commits (10+)

  • b731c64 feat: Add local MCP server integration for tool registration, discovery, and invocation in Open WebUI
  • a088bb8 feat: Add product requirements document for local MCP tool integration in Open WebUI
  • 7779a25 Create GroupPRD.md
  • 10afdfb Update PRD
  • 7132de6 feat: Enhance tool registration documentation for external OpenAPI Tool Servers and internal Python tools
  • 828bb66 docs: Update documentation for local MCP tool integration and clarify tool invocation processes
  • 3a7bb84 docs: Update PRD writing guidelines to enhance clarity, completeness, and error handling strategies
  • 2d82aef Enhance tool registration documentation and introduce mcpo README
  • a4fed4d feat: Enhance local tool integration by ensuring isolation in multi-user environments
  • 8608e08 feat: implement group synchronization service for user login

📊 Changes

167 files changed (+10354 additions, -883 deletions)

View changed files

.claude/settings.local.json (+14 -0)
.claude/skills/dockerbuild-openwebui/SKILL.md (+84 -0)
.devcontainer/devcontainer.json (+82 -0)
📝 .gitignore (+10 -0)
.vscode/Microsoft.PowerShell_profile.ps1 (+14 -0)
.vscode/launch.json (+35 -0)
📝 Dockerfile (+22 -2)
📝 LICENSE (+1 -1)
📝 README.md (+55 -41)
THIRD_PARTY_LICENSES (+42 -0)
acp-3825-search-plan-agent-buttons/README.md (+63 -0)
acp-3835-selectable-knowledge-source/README.md (+69 -0)
backend/DB-Migration-ACP-3780/dev-openwebui-schema.sqlserver.sql (+360 -0)
backend/DB-Migration-ACP-3780/import_data_to_mssql.py (+541 -0)
backend/DB-Migration-ACP-3780/資料庫遷移標準作業程序 (SOP).md (+1 -0)
📝 backend/open_webui/config.py (+30 -2)
📝 backend/open_webui/env.py (+40 -3)
📝 backend/open_webui/functions.py (+3 -1)
📝 backend/open_webui/internal/db.py (+18 -1)
📝 backend/open_webui/main.py (+23 -7)

...and 80 more files

📄 Description

Summary

Implements the open-webui half of end-to-end NTID propagation per IT mandate (Confluence: User Header Modification, deadline 2026-05-02).

After OIDC login, fetch the user's NTID from Microsoft Graph (onPremisesSamAccountName), persist it on the user row, and forward it in the chat-completions payload so the downstream pipeline can emit user: <NTID> to https://llm-api.amd.com.

Full design doc: docs/dev-plans/ntid-header-propagation.md (already on main).

Changes

File What
backend/open_webui/models/users.py New dedicated ntid String(64) column on User + UserModel field + insert_new_user(ntid=...) kwarg. Indexed for reverse lookup.
backend/open_webui/utils/oauth.py After OIDC sub validation, call Microsoft Graph /me?$select=onPremisesSamAccountName using the access_token. Persist on both new-user creation and existing-user re-login (refresh on AD drift). All failures logged at WARN, never block login.
backend/open_webui/routers/openai.py Include user.ntid in the body sent to pipeline-flagged models (gated by existing if "pipeline" in model and model.get("pipeline")).

Total: 3 files, +49 lines (no removals).

Out-of-band actions required (pre-merge / pre-deploy)

1. DDL — must run BEFORE deploy

ALTER TABLE [user] ADD ntid NVARCHAR(64) NULL;
CREATE INDEX IX_user_ntid ON [user](ntid) WHERE ntid IS NOT NULL;

Without this, SQLAlchemy reads will fail with column user.ntid does not exist.

2. Env var

OAUTH_SCOPES must include User.Read:

OAUTH_SCOPES=openid email profile User.Read

The App Registration (pdase-cepm-wapp) already requests this Graph permission. First-time consent will either:

  • Be auto-handled per-user (User.Read is low-privilege, no admin consent required), OR
  • Be admin-granted tenant-wide via Azure Portal → API permissions → "Grant admin consent" (smoother UX).

3. Pipeline counterpart

C:\Github\pipeline repo carries the matching ContextVar + CustomHTTPLLM._get_headers() injection (separate PR). Both must ship together — open-webui alone has no effect on the gateway.

Design notes

  • Path C (Graph API) chosen over Path A (Entra optional claim) because the App Registration already has User.Read consented and Path A requires a claim mapping policy (admin-only Graph API config).
  • Path B (pipeline-side AD lookup) kept as fallback if Graph fetch proves unreliable; pipeline contract (body.user.ntid) is unchanged.
  • Empty NTID → header omitted entirely (per IT FAQ; gateway monitors non-compliance separately, empty string would be malformed).
  • Non-OIDC users (bootstrap admin, local-auth) keep ntid = NULL and are excluded from the gateway header. They should use a service-account NTID per IT FAQ.

Test plan

  • Run DDL on dev DB (dvse-cepm-sqlmi/openwebui)
  • Set OAUTH_SCOPES=openid email profile User.Read in dev docker-compose.yml
  • docker compose build openwebui && docker compose up -d openwebui
  • Log into dev OWUI → accept consent prompt (first time only)
  • docker compose logs openwebui | grep '\[NTID\]' — expect [NTID] fetched for ...: <your-ntid> or [NTID] set on new user ...
  • SELECT email, ntid FROM [user] WHERE email = '<your-email>'ntid populated
  • Send chat using a pipeline-flagged model
  • docker compose logs pipelines | grep -i 'LLM_REQUEST' — confirm user: header present on outbound to https://llm-api.amd.com
  • (Optional) tcpdump -A -i any 'host llm-api.amd.com' on dev VM for end-to-end wire confirmation

Rollback

Both changes are additive (new column, new field). Revert is git revert + drop column. The Graph call is wrapped in try/except so disabling it doesn't break login.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/24599 **Author:** [@datar-ai](https://github.com/datar-ai) **Created:** 5/12/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `feat/ntid-user-header-propagation` --- ### 📝 Commits (10+) - [`b731c64`](https://github.com/open-webui/open-webui/commit/b731c64b2d4e4a43c672981e4e5d5beac93cb05c) feat: Add local MCP server integration for tool registration, discovery, and invocation in Open WebUI - [`a088bb8`](https://github.com/open-webui/open-webui/commit/a088bb8a413cbc28d0e2a2727c896b51a8b05053) feat: Add product requirements document for local MCP tool integration in Open WebUI - [`7779a25`](https://github.com/open-webui/open-webui/commit/7779a25a13025effba1dc8512b3e34e01d7735bd) Create GroupPRD.md - [`10afdfb`](https://github.com/open-webui/open-webui/commit/10afdfb3845a1a9c9523fdf6cf9f9ffe87c830d0) Update PRD - [`7132de6`](https://github.com/open-webui/open-webui/commit/7132de63be138dc8ce1f537f3655446ff638f7d4) feat: Enhance tool registration documentation for external OpenAPI Tool Servers and internal Python tools - [`828bb66`](https://github.com/open-webui/open-webui/commit/828bb662907c26735e34902f50b9ba6074d74aa0) docs: Update documentation for local MCP tool integration and clarify tool invocation processes - [`3a7bb84`](https://github.com/open-webui/open-webui/commit/3a7bb84cff26c4cf4cbbb6b48eaf056858224e30) docs: Update PRD writing guidelines to enhance clarity, completeness, and error handling strategies - [`2d82aef`](https://github.com/open-webui/open-webui/commit/2d82aef1d1c69bb6f4d38be5df4b6a0fba9a78ee) Enhance tool registration documentation and introduce mcpo README - [`a4fed4d`](https://github.com/open-webui/open-webui/commit/a4fed4d7267f2c7bf1f7f14d9a41877610df05f0) feat: Enhance local tool integration by ensuring isolation in multi-user environments - [`8608e08`](https://github.com/open-webui/open-webui/commit/8608e086174feedb22fc45d4795580b4f4ce33ce) feat: implement group synchronization service for user login ### 📊 Changes **167 files changed** (+10354 additions, -883 deletions) <details> <summary>View changed files</summary> ➕ `.claude/settings.local.json` (+14 -0) ➕ `.claude/skills/dockerbuild-openwebui/SKILL.md` (+84 -0) ➕ `.devcontainer/devcontainer.json` (+82 -0) 📝 `.gitignore` (+10 -0) ➕ `.vscode/Microsoft.PowerShell_profile.ps1` (+14 -0) ➕ `.vscode/launch.json` (+35 -0) 📝 `Dockerfile` (+22 -2) 📝 `LICENSE` (+1 -1) 📝 `README.md` (+55 -41) ➕ `THIRD_PARTY_LICENSES` (+42 -0) ➕ `acp-3825-search-plan-agent-buttons/README.md` (+63 -0) ➕ `acp-3835-selectable-knowledge-source/README.md` (+69 -0) ➕ `backend/DB-Migration-ACP-3780/dev-openwebui-schema.sqlserver.sql` (+360 -0) ➕ `backend/DB-Migration-ACP-3780/import_data_to_mssql.py` (+541 -0) ➕ `backend/DB-Migration-ACP-3780/資料庫遷移標準作業程序 (SOP).md` (+1 -0) 📝 `backend/open_webui/config.py` (+30 -2) 📝 `backend/open_webui/env.py` (+40 -3) 📝 `backend/open_webui/functions.py` (+3 -1) 📝 `backend/open_webui/internal/db.py` (+18 -1) 📝 `backend/open_webui/main.py` (+23 -7) _...and 80 more files_ </details> ### 📄 Description ## Summary Implements the **open-webui half** of end-to-end NTID propagation per IT mandate ([Confluence: User Header Modification](https://amd.atlassian.net/wiki/spaces/SI/pages/1655519770/User+Header+Modification), deadline **2026-05-02**). After OIDC login, fetch the user's NTID from Microsoft Graph (`onPremisesSamAccountName`), persist it on the `user` row, and forward it in the chat-completions payload so the downstream pipeline can emit `user: <NTID>` to `https://llm-api.amd.com`. Full design doc: `docs/dev-plans/ntid-header-propagation.md` (already on main). ## Changes | File | What | |---|---| | `backend/open_webui/models/users.py` | New dedicated `ntid String(64)` column on `User` + `UserModel` field + `insert_new_user(ntid=...)` kwarg. Indexed for reverse lookup. | | `backend/open_webui/utils/oauth.py` | After OIDC sub validation, call Microsoft Graph `/me?$select=onPremisesSamAccountName` using the access_token. Persist on both new-user creation and existing-user re-login (refresh on AD drift). All failures logged at WARN, never block login. | | `backend/open_webui/routers/openai.py` | Include `user.ntid` in the body sent to pipeline-flagged models (gated by existing `if "pipeline" in model and model.get("pipeline")`). | Total: **3 files, +49 lines** (no removals). ## Out-of-band actions required (pre-merge / pre-deploy) ### 1. DDL — must run BEFORE deploy ```sql ALTER TABLE [user] ADD ntid NVARCHAR(64) NULL; CREATE INDEX IX_user_ntid ON [user](ntid) WHERE ntid IS NOT NULL; ``` Without this, SQLAlchemy reads will fail with `column user.ntid does not exist`. ### 2. Env var `OAUTH_SCOPES` must include `User.Read`: ``` OAUTH_SCOPES=openid email profile User.Read ``` The App Registration (`pdase-cepm-wapp`) already requests this Graph permission. First-time consent will either: - Be auto-handled per-user (User.Read is low-privilege, no admin consent required), OR - Be admin-granted tenant-wide via Azure Portal → API permissions → "Grant admin consent" (smoother UX). ### 3. Pipeline counterpart `C:\Github\pipeline` repo carries the matching `ContextVar` + `CustomHTTPLLM._get_headers()` injection (separate PR). Both must ship together — open-webui alone has no effect on the gateway. ## Design notes - **Path C (Graph API)** chosen over Path A (Entra optional claim) because the App Registration already has User.Read consented and Path A requires a claim mapping policy (admin-only Graph API config). - **Path B (pipeline-side AD lookup)** kept as fallback if Graph fetch proves unreliable; pipeline contract (`body.user.ntid`) is unchanged. - **Empty NTID → header omitted entirely** (per IT FAQ; gateway monitors non-compliance separately, empty string would be malformed). - **Non-OIDC users** (bootstrap admin, local-auth) keep `ntid = NULL` and are excluded from the gateway header. They should use a service-account NTID per IT FAQ. ## Test plan - [ ] Run DDL on dev DB (`dvse-cepm-sqlmi/openwebui`) - [ ] Set `OAUTH_SCOPES=openid email profile User.Read` in dev `docker-compose.yml` - [ ] `docker compose build openwebui && docker compose up -d openwebui` - [ ] Log into dev OWUI → accept consent prompt (first time only) - [ ] `docker compose logs openwebui | grep '\[NTID\]'` — expect `[NTID] fetched for ...: <your-ntid>` or `[NTID] set on new user ...` - [ ] `SELECT email, ntid FROM [user] WHERE email = '<your-email>'` — `ntid` populated - [ ] Send chat using a pipeline-flagged model - [ ] `docker compose logs pipelines | grep -i 'LLM_REQUEST'` — confirm `user:` header present on outbound to `https://llm-api.amd.com` - [ ] (Optional) `tcpdump -A -i any 'host llm-api.amd.com'` on dev VM for end-to-end wire confirmation ## Rollback Both changes are additive (new column, new field). Revert is `git revert` + drop column. The Graph call is wrapped in try/except so disabling it doesn't break login. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-13 17:09:08 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#82609