LearnNewsExamplesServices
Frontmatter
id12378
title[neo] GitLab-PAT Bearer auth mode in AuthService — no `aud`, naked 401 (Sub of #12377)
stateClosed
labels
enhancementai
assigneesneo-opus-ada
createdAtJun 2, 2026, 2:02 PM
updatedAtJun 7, 2026, 7:18 PM
githubUrlhttps://github.com/neomjs/neo/issues/12378
authorneo-opus-ada
commentsCount1
parentIssue12377
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 2, 2026, 5:35 PM

[neo] GitLab-PAT Bearer auth mode in AuthService — no aud, naked 401 (Sub of #12377)

neo-opus-ada
neo-opus-ada commented on Jun 2, 2026, 2:02 PM

Sub of #12377 (foundation). Owner: @neo-opus-ada.

Goal

Add a GitLab Personal Access Token Bearer auth mode to ai/mcp/server/shared/services/AuthService.mjs. A user/agent sends Authorization: Bearer <GitLab-PAT>; the server validates the PAT against GitLab's REST API (GET <gitlabBase>/api/v4/user, which a read_user-scoped PAT can hit) and uses the returned username as the MCP identity (userId). No browser OAuth, no cookie.

Why (V-B-A)

AuthService today does OIDC introspection + requireBearerAuth + enforces aud == MCP-server URL (rejects a raw PAT, which has no such audience) + advertises OAuth PRM via mcpAuthMetadataRouter (which triggers MCP Inspector v0.21+'s OAuth-DCR → fails, since GitLab has no DCR). This mode bypasses both: validate via the GitLab API directly, advertise nothing.

Contract Ledger

Target Surface Source of Authority Behavior Fallback / Edge Evidence
GitLab-PAT Bearer mode (AuthService) this sub Bearer <PAT>GET /api/v4/useruserId = username; no aud check invalid/expired PAT → 401; missing header → naked 401, no PRM/WWW-Authenticate unit test on the verifier + a live /user probe
config gate (e.g. NEO_AUTH_GITLAB_PAT + GitLab API base URL) this sub enables the mode; GitLab base configurable unset → existing OIDC + trustProxyIdentity paths unchanged config-shape test

Acceptance Criteria

  1. With the mode enabled, Authorization: Bearer <valid GitLab PAT> authenticates; identity = the GitLab username from /api/v4/user.
  2. Invalid/expired PAT → 401.
  3. No aud requirement in this mode (PATs aren't audience-scoped); the OIDC aud enforcement is not applied.
  4. Unauthenticated request → naked 401 with no PRM advertisement / WWW-Authenticate — so MCP Inspector v0.21+ does not trigger OAuth-DCR.
  5. Config-gated (new mode flag + configurable GitLab API base); existing OIDC-introspection and trustProxyIdentity modes are unaffected.
  6. Unit test covers the PAT verifier (success / failure / identity extraction).
  7. Docs note the required PAT scope (read_user).

This sub's auth-mode contract (the verifier + config shape) must be visible before sub #2 (Inspector compat) starts — foundation-first per the epic DAG.

tobiu referenced in commit 26c4485 - "feat(ai): GitLab-PAT Bearer auth mode for MCP servers (#12378) (#12383) on Jun 2, 2026, 5:35 PM
tobiu closed this issue on Jun 2, 2026, 5:35 PM