Repository navigation
Commit c34626b
authored
docs(auth): document HTTP verification requirements and pin them with tests (#1640)
## Summary
Answers the documentation ask in #1625: when HTTP verification fails
there is no way to tell whether the fault is the key, the file, or the
Registry's ability to reach the endpoint, and the Registry's egress
addresses are not a fixed set that can be allowlisted.
### Documented fetch contract
(`docs/modelcontextprotocol-io/authentication.mdx`)
New "Troubleshooting failed HTTP verification" subsection describing
what the Registry actually requests when `mcp-publisher login http`
runs, why a successful local `curl` proves nothing, and how to reproduce
the fetch from outside your own network:
- `GET https://<domain>/.well-known/mcp-registry-auth` with `Accept:
text/plain` and `User-Agent: mcp-registry/1.0`
- `200 OK` only — redirects are not followed, so a `3xx` fails
verification
- proof record of at most 4096 bytes, with surrounding whitespace
ignored
- 10 second budget for the whole request
- the request originates from Google Cloud, where the hosted Registry
runs, so per-request IP allowlisting is not a workable fix
It then lists the edge rules that break verification in practice
(WAF/bot-management challenges, geo-blocking or allowlists that exclude
cloud ranges, an unreachable `AAAA` record, redirects, an HTML error
page served with `200 OK`), how to read the Registry's own fetch error
out of the login failure, and where to fix it.
### The same contract is pinned by tests
(`internal/api/handlers/v0/auth/http_internal_test.go`)
These properties were previously untested: the existing fetcher tests
inject a custom `http.Client`, so the production client's redirect
policy was never exercised, and nothing asserted the request headers or
whitespace trimming.
- `TestHTTPKeyFetcherClient_DoesNotFollowRedirects` — a `301` must fail
verification and the redirect target must never be requested.
- `TestHTTPKeyFetcherClient_TimeoutAndRequestHeaders` — pins the 10
second timeout, the two documented request headers, and `TrimSpace` on
the proof record.
- `TestHTTPKeyFetcher_RejectsResponseAboveDocumentedLimit` — a `200 OK`
body above 4096 bytes fails.
To make the production client testable, client construction moved into
`newHTTPKeyFetcherClient(transport http.RoundTripper)`;
`NewDefaultHTTPKeyFetcher` passes the same cloned transport with
`safeDialContext`, so production behavior is unchanged. This PR changes
no production behavior.
## Verification
- `go build ./...` — clean.
- `go vet ./...` — clean.
- `gofmt -l internal/` — clean.
- `go test ./internal/api/handlers/v0/auth/ -count=1` — `ok` (whole
package passes).
- The redirect test is load-bearing: deleting the `CheckRedirect` policy
from `newHTTPKeyFetcherClient` makes it fail with `stopped after 10
redirects`, which is exactly the regression it guards.
- `go test ./internal/api/handlers/v0/ -count=1` fails on this machine
only because that suite needs PostgreSQL from `docker-compose up -d
postgres`; unrelated to this change. `golangci-lint` is not installed
locally, so `make lint` was not run.
Related to #1625.
> AI assistance disclosure: AI was used to discover this opportunity and
draft the change or text. The submission was checked against the
prepared artifact and recorded verification evidence.
Co-authored-by: ump45nose <ump45nose@users.noreply.github.com>1 parent cd511f4 commit c34626b
3 files changed
Lines changed: 190 additions & 9 deletions
File tree
- docs/modelcontextprotocol-io
- internal/api/handlers/v0/auth
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
330 | 330 | | |
331 | 331 | | |
332 | 332 | | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
50 | 59 | | |
| 60 | + | |
51 | 61 | | |
52 | 62 | | |
53 | 63 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
4 | 7 | | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
5 | 11 | | |
| 12 | + | |
6 | 13 | | |
7 | 14 | | |
8 | 15 | | |
| |||
78 | 85 | | |
79 | 86 | | |
80 | 87 | | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
0 commit comments