@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
|
@@ -335,8 +335,10 @@ export interface McpAuthOptions {
|
|
|
335
335
|
readonly lifetimes?: Lifetimes;
|
|
336
336
|
/**
|
|
337
337
|
* Seconds after a refresh token is used during which presenting it again
|
|
338
|
-
*
|
|
339
|
-
* of ending the grant;
|
|
338
|
+
* (a lost response, a retried request) returns the pair the first use
|
|
339
|
+
* issued instead of ending the grant; with a store that lacks
|
|
340
|
+
* `putRefreshTokenReplacement`, a new access token only. Never a second
|
|
341
|
+
* refresh token chain. `0` turns the window off. Default: 10.
|
|
340
342
|
*/
|
|
341
343
|
readonly refreshReuseGraceSeconds?: number;
|
|
342
344
|
/** Accept Client ID Metadata Document client ids. Default: `true`. */
|
|
@@ -583,6 +585,14 @@ export interface McpAuthOptions {
|
|
|
583
585
|
* issuer and resource, for development. Default: `false`.
|
|
584
586
|
*/
|
|
585
587
|
readonly allowInsecureLocalhost?: boolean;
|
|
588
|
+
/**
|
|
589
|
+
* Send `Strict-Transport-Security: max-age=63072000; includeSubDomains`
|
|
590
|
+
* on every response this package builds (endpoints, pages, redirects and
|
|
591
|
+
* `authenticate` / `unauthorized` refusals). Set `false` only when a proxy
|
|
592
|
+
* in front already sets the header, or when the issuer's subdomains must
|
|
593
|
+
* stay reachable over plain HTTP. Default: `true`.
|
|
594
|
+
*/
|
|
595
|
+
readonly strictTransportSecurity?: boolean;
|
|
586
596
|
/**
|
|
587
597
|
* Clock in milliseconds since the epoch, for tests. A non-finite value
|
|
588
598
|
* makes the request fail instead of disabling expiry checks.
|
|
@@ -366,6 +366,14 @@ export interface RefreshTokenRecord {
|
|
|
366
366
|
readonly expiresAt: number;
|
|
367
367
|
/** Set once, atomically, by `OAuthStore.useRefreshToken`. */
|
|
368
368
|
readonly usedAt?: number;
|
|
369
|
+
/**
|
|
370
|
+
* The access and refresh token pair this token was exchanged for,
|
|
371
|
+
* encrypted by the `SecretSealer`. Set by the optional
|
|
372
|
+
* `OAuthStore.putRefreshTokenReplacement` after the token is spent, and
|
|
373
|
+
* returned by `getRefreshToken` and `useRefreshToken` from then on, so a
|
|
374
|
+
* retry inside `refreshReuseGraceSeconds` receives that same pair.
|
|
375
|
+
*/
|
|
376
|
+
readonly sealedReplacement?: string;
|
|
369
377
|
}
|
|
370
378
|
/**
|
|
371
379
|
* Result of `OAuthStore.useRefreshToken`.
|
|
@@ -35,8 +35,9 @@ import type { AccessTokenRecord, AuthorizationCodeRecord, ClientRecord, ConsentR
|
|
|
35
35
|
* an idle period, and when a size cap is reached evict the least recently
|
|
36
36
|
* used grant-less dynamic client first; never evict `static` clients.
|
|
37
37
|
*
|
|
38
|
-
* Only hashes of tokens and codes reach the store. Upstream tokens
|
|
39
|
-
*
|
|
38
|
+
* Only hashes of tokens and codes reach the store. Upstream tokens, and the
|
|
39
|
+
* pair a refresh token was exchanged for (`putRefreshTokenReplacement`),
|
|
40
|
+
* arrive already encrypted by the `SecretSealer`.
|
|
40
41
|
*
|
|
41
42
|
* @example
|
|
42
43
|
* ```ts
|
|
@@ -179,6 +180,20 @@ export interface OAuthStore {
|
|
|
179
180
|
getRefreshToken(tokenHash: string): Promise<RefreshTokenRecord | undefined>;
|
|
180
181
|
/** Atomically set `usedAt` if it is not set yet. */
|
|
181
182
|
useRefreshToken(tokenHash: string, now: number): Promise<UsedRefreshToken | undefined>;
|
|
183
|
+
/**
|
|
184
|
+
* Optional, recommended: save `sealedReplacement` on the (already used)
|
|
185
|
+
* refresh token record `tokenHash`, keeping every other field, `usedAt`
|
|
186
|
+
* included. `getRefreshToken` and `useRefreshToken` must return it from
|
|
187
|
+
* then on. A later write replaces an earlier one; nothing happens when the
|
|
188
|
+
* record is gone.
|
|
189
|
+
*
|
|
190
|
+
* With it, a refresh token presented again inside
|
|
191
|
+
* `refreshReuseGraceSeconds` receives exactly the pair its first exchange
|
|
192
|
+
* issued, so a copied refresh token can never start a second token chain.
|
|
193
|
+
* Without it, such a retry receives a new access token only, with no
|
|
194
|
+
* refresh token.
|
|
195
|
+
*/
|
|
196
|
+
putRefreshTokenReplacement?(tokenHash: string, sealedReplacement: string): Promise<void>;
|
|
182
197
|
/**
|
|
183
198
|
* Optional: remember the answer to a consent submission for a few
|
|
184
199
|
* seconds, keyed by a hash of the browser cookie and the form token, so a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gydr-ai/mcp-oauth",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "OAuth 2.1 authorization server and resource-server guard for remote MCP servers, in front of any OIDC identity provider. No token passthrough, consent on every authorization, DCR and Client ID Metadata Documents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|