@gydr-ai/mcp-oauth 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -35
- package/dist/index.js +10 -10
- package/dist/index.js.map +3 -3
- package/dist/types/helpers/responses.d.ts +5 -1
- package/dist/types/interfaces/options.d.ts +12 -2
- package/dist/types/interfaces/records.d.ts +8 -0
- package/dist/types/interfaces/store.d.ts +17 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -431,10 +431,36 @@ verifier against it first.
|
|
|
431
431
|
(sent on refresh under `lifetimes.grantIdle`); `putGrant` must keep the
|
|
432
432
|
whole record, including the optional `redirectUri`.
|
|
433
433
|
|
|
434
|
-
|
|
435
|
-
(answering a repeated
|
|
436
|
-
|
|
437
|
-
earlier one) and
|
|
434
|
+
Four methods are optional: `putRefreshTokenReplacement` (recommended; see
|
|
435
|
+
below), `putConsentOutcome` / `getConsentOutcome` (answering a repeated
|
|
436
|
+
consent submission; one submission writes twice, the "being decided" mark
|
|
437
|
+
and then the answer, so a later write replaces an earlier one) and
|
|
438
|
+
`listGrantsBySubject` (`revokeGrantsForSubject`).
|
|
439
|
+
|
|
440
|
+
**Refresh retries.** `putRefreshTokenReplacement(hash, sealedReplacement)`
|
|
441
|
+
saves, on the refresh token record just used, the pair it was exchanged
|
|
442
|
+
for, encrypted by your `SecretSealer`; keep every other field (`usedAt`
|
|
443
|
+
included) and return `sealedReplacement` from `getRefreshToken` and
|
|
444
|
+
`useRefreshToken` afterwards. A refresh token presented again within
|
|
445
|
+
`refreshReuseGraceSeconds` then receives exactly that pair, so a copied
|
|
446
|
+
token never starts a second chain: once either holder rotates the shared
|
|
447
|
+
pair, the other's next use is a replay and the grant ends. A retry that
|
|
448
|
+
arrives while the first exchange is still storing its pair gets
|
|
449
|
+
`503 temporarily_unavailable`. Without the method, a retry within the
|
|
450
|
+
window receives an access token only, with no refresh token, and the
|
|
451
|
+
client keeps the refresh token from the response it lost (re-presenting the
|
|
452
|
+
original one within the window if that response never arrived).
|
|
453
|
+
|
|
454
|
+
**Key length.** Any `client_id` a caller sends, up to 2,048 characters,
|
|
455
|
+
can reach `getClient`, and a Client ID Metadata Document URL of that length
|
|
456
|
+
reaches `getCachedClientMetadata` and `putCachedClientMetadata` as a key
|
|
457
|
+
(and grants and tokens carry it as a field). Some databases cap key or index
|
|
458
|
+
length near that (a DynamoDB partition key is at most 2,048 bytes, a MySQL
|
|
459
|
+
index prefix often 767 or 3,072 bytes), especially once you add a prefix.
|
|
460
|
+
Hash long ids into the key, or refuse them in the adapter (`getClient` and
|
|
461
|
+
`getCachedClientMetadata` resolving `undefined`, `putCachedClientMetadata`
|
|
462
|
+
skipping the write); never truncate one, since two ids would then share a
|
|
463
|
+
record, and never let a too-long key throw.
|
|
438
464
|
|
|
439
465
|
Good fits: PostgreSQL or MySQL (`UPDATE … WHERE used_at IS NULL`,
|
|
440
466
|
`DELETE … RETURNING`), Redis (`GETDEL`, Lua), MongoDB (`findOneAndUpdate`),
|
|
@@ -485,35 +511,36 @@ evict the least recently used grant-less dynamic client first when full.
|
|
|
485
511
|
|
|
486
512
|
### Options
|
|
487
513
|
|
|
488
|
-
| Option | Default | Meaning
|
|
489
|
-
| --------------------------------------- | ----------------------------------------------------------------------- |
|
|
490
|
-
| `issuer` | required | HTTPS URL; endpoints live under its path.
|
|
491
|
-
| `resource` | required | Canonical URL of your MCP endpoint, the audience of every token.
|
|
492
|
-
| `identityProvider` | required | `createOidcProvider(…)` or your own `IdentityProvider`.
|
|
493
|
-
| `store` | required | Your `OAuthStore`.
|
|
494
|
-
| `sealer` | required | `createAesGcmSealer(…)` or your own `SecretSealer`.
|
|
495
|
-
| `scopes` / `defaultScopes` | `["mcp"]` / all | Scopes offered, and those granted when none are asked for.
|
|
496
|
-
| `scopeDescriptions` | none | Consent-screen text per scope.
|
|
497
|
-
| `resourceName` | none | RFC 9728 `resource_name`.
|
|
498
|
-
| `clients` | none | Pre-registered public clients.
|
|
499
|
-
| `dynamicClientRegistration` | `true` | Serve `POST /register`. Deprecated by MCP 2026-07-28 in favour of metadata documents; `dynamicClientRegistration: false` turns it off.
|
|
500
|
-
| `clientIdMetadataDocuments` | `true` | Accept HTTPS URL client ids.
|
|
501
|
-
| `fetchClientMetadata(url, { signal })` | SSRF-safe fetcher | Replace how metadata documents are downloaded. Must stay SSRF-safe.
|
|
502
|
-
| `lifetimes` | see below | Token and flow lifetimes, in seconds.
|
|
503
|
-
| `limits` | see below | Sizes and counts.
|
|
504
|
-
| `defaultGrantTypes` | `["authorization_code"]` | Grant types for a client that registers or publishes none, applied at registration or fetch. Must include `authorization_code`. `clients` default to both.
|
|
505
|
-
| `refreshReuseGraceSeconds` | `10` | Retry window (0–300) for a just-used refresh token. `0` treats any reuse as replay.
|
|
506
|
-
| `
|
|
507
|
-
| `
|
|
508
|
-
| `
|
|
509
|
-
| `
|
|
510
|
-
| `
|
|
511
|
-
| `
|
|
512
|
-
| `
|
|
513
|
-
| `
|
|
514
|
-
|
|
|
515
|
-
|
|
|
516
|
-
| `
|
|
514
|
+
| Option | Default | Meaning |
|
|
515
|
+
| --------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
516
|
+
| `issuer` | required | HTTPS URL; endpoints live under its path. |
|
|
517
|
+
| `resource` | required | Canonical URL of your MCP endpoint, the audience of every token. |
|
|
518
|
+
| `identityProvider` | required | `createOidcProvider(…)` or your own `IdentityProvider`. |
|
|
519
|
+
| `store` | required | Your `OAuthStore`. |
|
|
520
|
+
| `sealer` | required | `createAesGcmSealer(…)` or your own `SecretSealer`. |
|
|
521
|
+
| `scopes` / `defaultScopes` | `["mcp"]` / all | Scopes offered, and those granted when none are asked for. |
|
|
522
|
+
| `scopeDescriptions` | none | Consent-screen text per scope. |
|
|
523
|
+
| `resourceName` | none | RFC 9728 `resource_name`. |
|
|
524
|
+
| `clients` | none | Pre-registered public clients. |
|
|
525
|
+
| `dynamicClientRegistration` | `true` | Serve `POST /register`. Deprecated by MCP 2026-07-28 in favour of metadata documents; `dynamicClientRegistration: false` turns it off. |
|
|
526
|
+
| `clientIdMetadataDocuments` | `true` | Accept HTTPS URL client ids. |
|
|
527
|
+
| `fetchClientMetadata(url, { signal })` | SSRF-safe fetcher | Replace how metadata documents are downloaded. Must stay SSRF-safe. |
|
|
528
|
+
| `lifetimes` | see below | Token and flow lifetimes, in seconds. |
|
|
529
|
+
| `limits` | see below | Sizes and counts. |
|
|
530
|
+
| `defaultGrantTypes` | `["authorization_code"]` | Grant types for a client that registers or publishes none, applied at registration or fetch. Must include `authorization_code`. `clients` default to both. |
|
|
531
|
+
| `refreshReuseGraceSeconds` | `10` | Retry window (0–300) for a just-used refresh token: a retry gets the same pair again (see `putRefreshTokenReplacement`), never a second chain. `0` treats any reuse as replay. |
|
|
532
|
+
| `strictTransportSecurity` | `true` | Send `Strict-Transport-Security: max-age=63072000; includeSubDomains` on every response the package builds. `false` only if your proxy already sets it. |
|
|
533
|
+
| `consentReplaySeconds` | `10` | Window (0–60) in which a repeated consent submission from the same browser gets the same redirect. |
|
|
534
|
+
| `scriptHashes` | none | `sha256-…` hashes of inline scripts a custom consent page may run. |
|
|
535
|
+
| `paths` | `/authorize`, `/callback`, `/consent`, `/token`, `/register`, `/revoke` | Route paths under the issuer path: one leading `/`, no `//`, `\`, dot segments or whitespace, distinct, and never a metadata path or the resource path. |
|
|
536
|
+
| `cookiePrefix` | `__Host-mcp-auth-` | Must start with `__Host-`. |
|
|
537
|
+
| `rateLimit(key, scope)` | none | Resolve `true` to continue; anything else (including a throw) answers 429. |
|
|
538
|
+
| `getClientIp(request)` / `trustProxy` | none / `false` | Rate-limit key. `trustProxy` uses the right-most `X-Forwarded-For` entry. |
|
|
539
|
+
| `renderConsentPage` / `renderErrorPage` | built in | Your own pages; see `ConsentPageContext`. |
|
|
540
|
+
| `onEvent(event)` | none | Typed audit events; never contain secrets. |
|
|
541
|
+
| policy and enrichment hooks | none | See [Extending safely](#extending-safely). |
|
|
542
|
+
| `allowInsecureLocalhost` | `false` | Allow an `http://localhost` issuer and resource in development. |
|
|
543
|
+
| `now` | `Date.now` | Clock, for tests. A non-finite value fails the request instead of disabling expiry checks. |
|
|
517
544
|
|
|
518
545
|
<details>
|
|
519
546
|
<summary><strong><code>lifetimes</code></strong> (seconds)</summary>
|
|
@@ -634,7 +661,7 @@ off, and concurrent requests for one URL share a download.
|
|
|
634
661
|
obtained.
|
|
635
662
|
- Pages send a strict Content-Security-Policy, `X-Frame-Options: DENY`,
|
|
636
663
|
`Cache-Control: no-store` and `Referrer-Policy: no-referrer`, and escape
|
|
637
|
-
every value. Client names with invisible or formatting characters are
|
|
664
|
+
every value. Every response carries `Strict-Transport-Security`. Client names with invisible or formatting characters are
|
|
638
665
|
refused.
|
|
639
666
|
- Tokens are 256-bit random values, stored only as SHA-256 hashes, bound to
|
|
640
667
|
your resource and checked against a live grant on every request. Refresh
|
|
@@ -659,7 +686,9 @@ off, and concurrent requests for one URL share a download.
|
|
|
659
686
|
rotates refresh tokens with no grace period and several processes may
|
|
660
687
|
renew one grant at once, route a grant's renewals to one process.
|
|
661
688
|
- Catch a refresh token copied and used within `refreshReuseGraceSeconds`
|
|
662
|
-
of the real use
|
|
689
|
+
of the real use at that moment: inside the window both holders get the
|
|
690
|
+
same pair, and the grant ends only when their chains diverge. Use `0` if
|
|
691
|
+
your clients never retry.
|
|
663
692
|
- Protect against a compromised browser, a client the person chose to
|
|
664
693
|
approve, or a compromised identity provider.
|
|
665
694
|
|