---
id: 12391
title: 'ClientAuthentication.md: add the OAuth browser-login client path'
state: CLOSED
labels:
  - documentation
  - enhancement
  - ai
assignees:
  - neo-opus-ada
createdAt: '2026-06-02T18:32:08Z'
updatedAt: '2026-06-07T17:18:15Z'
githubUrl: 'https://github.com/neomjs/neo/issues/12391'
author: neo-opus-ada
commentsCount: 0
parentIssue: null
subIssues: []
subIssuesCompleted: 0
subIssuesTotal: 0
blockedBy: []
blocking: []
closedAt: '2026-06-02T19:34:37Z'
---
# ClientAuthentication.md: add the OAuth browser-login client path

## Context

Settling the recommended client-auth posture for a GitLab-backed cloud MCP deployment converged on: **OAuth browser-login (via a pre-registered GitLab OAuth app) as the primary path, with a Personal Access Token only as a fallback.** That recommendation is not yet reflected in neo's canonical cloud-deployment docs.

`learn/agentos/cloud-deployment/ClientAuthentication.md` (#12380) documents only the PAT path and defers all OAuth to `learn/agentos/tooling/Authorization.md` — but `Authorization.md` covers the **server-side OIDC mode** (Keycloak/Google/OIDC with PRM + introspection + `aud`), not the path we actually recommend: a server in `gitlab-pat` bearer mode (bare `401`, token-agnostic `/api/v4/user` validation) where the **client** runs an OAuth browser login to mint a short-lived bearer.

## The Problem

There is no canonical neo doc for the recommended, verified path:

- The server runs `gitlab-pat` mode → emits a **bare `401`** (no Protected-Resource-Metadata, since GitLab has no DCR — see `McpInspectorCompatibility.md`).
- The client therefore cannot auto-discover the Authorization Server; it must be pointed at GitLab explicitly via an `authServerMetadataUrl`-style override + a **pre-registered** OAuth `client_id` (GitLab has no DCR).
- The client completes OAuth 2.1 auth-code + PKCE (browser SSO/2FA), holds a **short-lived, auto-refreshed** access token, and sends it as the bearer. The server validates it via `/api/v4/user` — identical to a PAT, because the verifier is token-type-agnostic.

This is the enterprise-appropriate path (short-lived, SSO, no static secret in config). It's the missing canonical recipe; today readers only find PAT.

## The Architectural Reality

- `learn/agentos/cloud-deployment/ClientAuthentication.md` (#12380) — currently PAT-only, with a "Pending — MCP Inspector recipe" placeholder, and an "OAuth → see Authorization.md" deferral that points at the wrong (server-OIDC) mode for this case.
- The client recipe is harness-specific: a desktop MCP client (e.g. Claude Code/Desktop ≥ the version exposing `oauth.authServerMetadataUrl`) supports pointing at the AS metadata + a pre-registered `client_id` + `callbackPort` + `scopes` against a bare-`401` server. The verified mechanism is `authServerMetadataUrl` → the AS's `/.well-known/openid-configuration`, redirect `http://localhost:<port>/callback`, scope `read_user`.

## The Fix

Extend `ClientAuthentication.md` with an **OAuth browser-login** section, presented as the primary path:

1. The model: one server contract (validate a GitLab bearer), two client ways to mint it — OAuth access token (preferred) or PAT (fallback).
2. One-time: register a GitLab OAuth app (`read_user`, per-harness redirect URIs, no DCR needed).
3. The client recipe for the bare-`401` case: the `authServerMetadataUrl` override + pre-registered `client_id` + `callbackPort` + `scopes`. Per-harness, with explicit "verified" vs "documented-not-yet-verified" status.
4. Reframe PAT as the explicit fallback (Inspector / headless-CI / scripts); fill the pending Inspector recipe (cross-ref #12379).
5. Add the honest **audience caveat** (no RFC 8707 on GitLab → validates "a valid user," not "issued for this server") and point at the verifier-hardening ticket #12390 for the enterprise-grade closure.

## Acceptance Criteria

- [ ] `ClientAuthentication.md` presents OAuth-browser-login as the primary path + PAT as the documented fallback.
- [ ] The bare-`401` + pre-registered-client OAuth recipe (`authServerMetadataUrl`, redirect URI, `read_user`) is documented with per-harness status.
- [ ] The audience caveat is stated and cross-links #12390.
- [ ] The "Pending Inspector recipe" placeholder is filled (cross-ref #12379).
- [ ] `learn/tree.json` nav unaffected or updated to mirror (no orphan group).

## Out of Scope

- The server-side OIDC/Keycloak mode (owned by `Authorization.md`).
- Any specific deployment's hostnames/secrets (those live in the deployment repo, not neo docs).
- Implementing the verifier hardening itself (that is #12390).

## Decision Record impact

`none` — documentation of an existing, shipped capability path.

## Related

- `ClientAuthentication.md` origin #12380 · Inspector compat #12379 · verifier hardening #12390 · epic #12377.

Origin Session ID: c279991f-11eb-4e89-9e38-2c9c4a78421e

Handoff Retrieval Hints: `query_raw_memories("OAuth browser-login authServerMetadataUrl gitlab-pat bare 401 pre-registered client_id read_user")`; anchor `learn/agentos/cloud-deployment/ClientAuthentication.md`.

Authored by @neo-opus-ada (claude-opus-4.8-1m)

## Timeline

- 2026-06-02T18:32:10Z @neo-opus-ada added the `documentation` label
- 2026-06-02T18:32:10Z @neo-opus-ada added the `enhancement` label
- 2026-06-02T18:32:10Z @neo-opus-ada added the `ai` label
- 2026-06-02T18:42:04Z @neo-opus-ada assigned to @neo-opus-ada
- 2026-06-02T18:48:35Z @neo-opus-ada cross-referenced by PR #12392
- 2026-06-02T18:54:48Z @neo-gpt cross-referenced by PR #12393
- 2026-06-02T19:02:38Z @neo-opus-ada referenced in commit `f86ad0c` - "docs(cloud-deployment): address #12392 review — config-bootstrap framing + precise hardening caveat (#12391)

Reframe the config note around autogeneration (initServerConfigs / bootstrapWorktree); --migrate-config is now the drift-fix, not the normal step. Tighten the authZ caveat to a precise opt-in hardening (GitLab /oauth/token/info app-binding + user/group allowlist). Co-Authored-By: neo-opus-4-7 <neo-opus-4-7@neomjs.com>"
- 2026-06-02T19:34:37Z @tobiu referenced in commit `312fceb` - "docs(cloud-deployment): OAuth browser-login path for gitlab-pat MCP auth (#12391) (#12392)

* docs(cloud-deployment): OAuth browser-login path for gitlab-pat MCP auth (#12391)

Reframe ClientAuthentication.md around the settled recommendation: the
gitlab-pat server mode validates any GitLab bearer via /api/v4/user, so present
OAuth browser-login (Path A, preferred for interactive harnesses) and PAT
(Path B, fallback). Add the authServerMetadataUrl client recipe for the
bare-401 / non-DCR case (Claude Code verified; Codex + Antigravity caveated),
fill the previously-pending MCP Inspector recipe, and add the
authentication-not-authorization caveat (GitLab issues no RFC 8707 aud).
tree.json nav label updated GitLab-PAT -> GitLab to mirror the broadened scope.

Co-Authored-By: neo-opus-4-7 <neo-opus-4-7@neomjs.com>

* docs(cloud-deployment): address #12392 review — config-bootstrap framing + precise hardening caveat (#12391)

Reframe the config note around autogeneration (initServerConfigs / bootstrapWorktree); --migrate-config is now the drift-fix, not the normal step. Tighten the authZ caveat to a precise opt-in hardening (GitLab /oauth/token/info app-binding + user/group allowlist). Co-Authored-By: neo-opus-4-7 <neo-opus-4-7@neomjs.com>

---------

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
- 2026-06-02T19:34:37Z @tobiu closed this issue
- 2026-06-02T20:03:23Z @neo-gpt cross-referenced by #12377

