@selvajs/server 1.5.0-beta.6 → 1.5.0-beta.7

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.
@@ -1 +1 @@
1
- {"version":3,"file":"me.d.ts","sourceRoot":"","sources":["../../src/handlers/me.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEjE,eAAO,MAAM,KAAK,EAAE,UAcnB,CAAC"}
1
+ {"version":3,"file":"me.d.ts","sourceRoot":"","sources":["../../src/handlers/me.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEjE,eAAO,MAAM,KAAK,EAAE,UAiBnB,CAAC"}
@@ -3,6 +3,7 @@
3
3
  * holder can see which org their credential resolved into — `actingOrgId` is
4
4
  * derived per request from the caller's membership, not frozen at mint time.
5
5
  */
6
+ import { formatApiScope } from '@selvajs/platform';
6
7
  import { requireCaller } from '../api/index.js';
7
8
  export const getMe = async (req) => {
8
9
  const { ctx, user } = requireCaller(req);
@@ -14,7 +15,10 @@ export const getMe = async (req) => {
14
15
  actingOrgId: ctx.actingOrgId,
15
16
  platformPermissions: ctx.platformPermissions,
16
17
  orgPermissions: ctx.orgPermissions,
17
- starredDefinitions: req.profile?.starredDefinitions ?? []
18
+ starredDefinitions: req.profile?.starredDefinitions ?? [],
19
+ ...(ctx.apiScope && {
20
+ apiToken: { id: ctx.apiScope.tokenId, scopes: ctx.apiScope.scopes.map(formatApiScope) }
21
+ })
18
22
  }
19
23
  };
20
24
  };
@@ -1 +1 @@
1
- {"version":3,"file":"me.js","sourceRoot":"","sources":["../../src/handlers/me.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,CAAC,MAAM,KAAK,GAAe,KAAK,EAAE,GAAG,EAAE,EAAE;IAC9C,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAEzC,OAAO;QACN,IAAI,EAAE;YACL,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW;YACrC,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;YAC5C,cAAc,EAAE,GAAG,CAAC,cAAc;YAClC,kBAAkB,EAAE,GAAG,CAAC,OAAO,EAAE,kBAAkB,IAAI,EAAE;SACzD;KACD,CAAC;AACH,CAAC,CAAC"}
1
+ {"version":3,"file":"me.js","sourceRoot":"","sources":["../../src/handlers/me.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,CAAC,MAAM,KAAK,GAAe,KAAK,EAAE,GAAG,EAAE,EAAE;IAC9C,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAEzC,OAAO;QACN,IAAI,EAAE;YACL,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW;YACrC,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;YAC5C,cAAc,EAAE,GAAG,CAAC,cAAc;YAClC,kBAAkB,EAAE,GAAG,CAAC,OAAO,EAAE,kBAAkB,IAAI,EAAE;YACzD,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI;gBACnB,QAAQ,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE;aACvF,CAAC;SACF;KACD,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * SvelteKit's form-submission CSRF check, with the two exemptions it can't
3
+ * express. A host turns the framework's own check off and calls this first.
4
+ *
5
+ * - A Selva API key in `Authorization`: a cross-site form can't set the header,
6
+ * and a `selva_` bearer never falls back to the cookie. API-token uploads are
7
+ * multipart with no `Origin`, which the framework check refuses. Any other
8
+ * `Authorization` (a proxy's id token) still gets checked: the request may run
9
+ * as the cookie session.
10
+ * - `exemptPaths`: endpoints that take a form body from servers, which send no
11
+ * `Origin` (the OAuth token endpoint, per RFC 6749).
12
+ */
13
+ export interface CsrfOptions {
14
+ /** Exact paths that accept cross-site form bodies. */
15
+ exemptPaths?: readonly string[];
16
+ }
17
+ export declare function isCrossSiteFormSubmission(request: Request, options?: CsrfOptions): boolean;
18
+ //# sourceMappingURL=csrf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csrf.d.ts","sourceRoot":"","sources":["../../src/http/csrf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAcH,MAAM,WAAW,WAAW;IAC3B,sDAAsD;IACtD,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAS9F"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * SvelteKit's form-submission CSRF check, with the two exemptions it can't
3
+ * express. A host turns the framework's own check off and calls this first.
4
+ *
5
+ * - A Selva API key in `Authorization`: a cross-site form can't set the header,
6
+ * and a `selva_` bearer never falls back to the cookie. API-token uploads are
7
+ * multipart with no `Origin`, which the framework check refuses. Any other
8
+ * `Authorization` (a proxy's id token) still gets checked: the request may run
9
+ * as the cookie session.
10
+ * - `exemptPaths`: endpoints that take a form body from servers, which send no
11
+ * `Origin` (the OAuth token endpoint, per RFC 6749).
12
+ */
13
+ import { API_TOKEN_PREFIX } from '../tokens/index.js';
14
+ const UNSAFE_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
15
+ // The content types a browser form can send without a CORS preflight, plus
16
+ // SvelteKit's own binary form encoding.
17
+ const FORM_TYPES = [
18
+ 'application/x-www-form-urlencoded',
19
+ 'multipart/form-data',
20
+ 'text/plain',
21
+ 'application/x-sveltekit-formdata'
22
+ ];
23
+ export function isCrossSiteFormSubmission(request, options = {}) {
24
+ if (!UNSAFE_METHODS.has(request.method))
25
+ return false;
26
+ const type = (request.headers.get('content-type') ?? '').split(';')[0].trim().toLowerCase();
27
+ if (!FORM_TYPES.includes(type))
28
+ return false;
29
+ const bearer = /^Bearer\s+(\S+)/i.exec(request.headers.get('authorization') ?? '')?.[1];
30
+ if (bearer?.startsWith(API_TOKEN_PREFIX))
31
+ return false;
32
+ const url = new URL(request.url);
33
+ if (options.exemptPaths?.includes(url.pathname))
34
+ return false;
35
+ return request.headers.get('origin') !== url.origin;
36
+ }
37
+ //# sourceMappingURL=csrf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csrf.js","sourceRoot":"","sources":["../../src/http/csrf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AACnE,2EAA2E;AAC3E,wCAAwC;AACxC,MAAM,UAAU,GAAG;IAClB,mCAAmC;IACnC,qBAAqB;IACrB,YAAY;IACZ,kCAAkC;CAClC,CAAC;AAOF,MAAM,UAAU,yBAAyB,CAAC,OAAgB,EAAE,UAAuB,EAAE;IACpF,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5F,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxF,IAAI,MAAM,EAAE,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,KAAK,CAAC;IACvD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9D,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC;AACrD,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export { safeRedirectTarget } from './redirect.js';
2
+ export { isCrossSiteFormSubmission, type CsrfOptions } from './csrf.js';
2
3
  export { declaredBodySizeExceeds, type HeadersLike } from './body-size.js';
3
4
  export { applySecurityHeaders, type SecurityHeaderOptions } from './security-headers.js';
4
5
  export { createRouteClassifier, type RouteClassifier, type RouteClassifierConfig } from './route-classifier.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,EACN,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EACN,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,EACN,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EACN,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,MAAM,gBAAgB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  // HTTP hardening helpers — transport-agnostic request/response guards.
2
2
  export { safeRedirectTarget } from './redirect.js';
3
+ export { isCrossSiteFormSubmission } from './csrf.js';
3
4
  export { declaredBodySizeExceeds } from './body-size.js';
4
5
  export { applySecurityHeaders } from './security-headers.js';
5
6
  export { createRouteClassifier } from './route-classifier.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAoB,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAA8B,MAAM,uBAAuB,CAAC;AACzF,OAAO,EACN,qBAAqB,EAGrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EAGpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAiC,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EACN,eAAe,EAIf,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAoB,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAoB,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAA8B,MAAM,uBAAuB,CAAC;AACzF,OAAO,EACN,qBAAqB,EAGrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EAGpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAiC,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EACN,eAAe,EAIf,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * OAuth 2.1 for MCP clients, with this instance as its own authorization server.
3
+ *
4
+ * The access token is an ordinary API token. The host mints it while the user is
5
+ * signed in, at consent, through the same path as Settings → API tokens; this
6
+ * module seals the raw key into the authorization code and hands it over at the
7
+ * token endpoint. So `/mcp` and `/api/v1` keep one credential type.
8
+ *
9
+ * Nothing here is stored. A registered client's id is its own signed metadata,
10
+ * and a code is its own encrypted grant, bound to the issuing origin. The only
11
+ * state is the set of redeemed codes, in the host's memory, so on several
12
+ * replicas a code could be redeemed once per replica within its minute, and only
13
+ * by whoever holds the PKCE verifier.
14
+ */
15
+ /** The scopes a grant can carry. Each maps to one org-wide API scope. */
16
+ export declare const OAUTH_SCOPES: readonly ["read", "solve"];
17
+ export type OAuthScope = (typeof OAUTH_SCOPES)[number];
18
+ export declare const MCP_PATH = "/mcp";
19
+ export declare class OAuthError extends Error {
20
+ /** RFC 6749 / 7591 error code. */
21
+ readonly error: string;
22
+ readonly status: number;
23
+ constructor(
24
+ /** RFC 6749 / 7591 error code. */
25
+ error: string, description: string, status?: number);
26
+ toBody(): {
27
+ error: string;
28
+ error_description: string;
29
+ };
30
+ }
31
+ export interface OAuthClient {
32
+ clientId: string;
33
+ /** Shown on the consent page. Unverified for a registered client: whatever it claimed. */
34
+ name: string;
35
+ redirectUris: string[];
36
+ }
37
+ /** A validated `/oauth/authorize` request, ready for the consent page. */
38
+ export interface AuthorizeRequest {
39
+ client: OAuthClient;
40
+ redirectUri: string;
41
+ state?: string;
42
+ codeChallenge: string;
43
+ scopes: OAuthScope[];
44
+ resource: string;
45
+ }
46
+ /** What the host minted at consent. `secret` is the raw API key. */
47
+ export interface Grant {
48
+ tokenId: string;
49
+ secret: string;
50
+ scopes: OAuthScope[];
51
+ expiresAt: string;
52
+ }
53
+ export interface OAuthServerOptions {
54
+ /** This instance's origin, e.g. `https://selva.example.com`. */
55
+ origin: string;
56
+ /** `SELVA_HMAC_KEY`. Rotating it invalidates registered clients and live codes. */
57
+ secret: string;
58
+ /**
59
+ * Fetches a Client ID Metadata Document. The URL comes from an unknown client,
60
+ * so the host must guard it against SSRF. Without it, URL client ids are refused.
61
+ */
62
+ fetchClientMetadata?: (url: string) => Promise<unknown>;
63
+ /**
64
+ * Redeemed code hashes and their expiry. Pass one map for the process so a
65
+ * rebuilt server (a new origin, a rotated secret) still refuses a replay.
66
+ */
67
+ redeemedCodes?: Map<string, number>;
68
+ now?: () => number;
69
+ }
70
+ interface HttpResult {
71
+ status: number;
72
+ body: Record<string, unknown>;
73
+ }
74
+ export declare function mcpResourceUrl(origin: string): string;
75
+ export declare function resourceMetadataUrl(origin: string): string;
76
+ /** RFC 9728. Claude uses only the first authorization server. */
77
+ export declare function protectedResourceMetadata(origin: string): {
78
+ resource: string;
79
+ authorization_servers: string[];
80
+ scopes_supported: ("read" | "solve")[];
81
+ bearer_methods_supported: string[];
82
+ };
83
+ /**
84
+ * RFC 8414. Claude picks Client ID Metadata Documents only when both
85
+ * `client_id_metadata_document_supported` and the `none` auth method appear.
86
+ */
87
+ export declare function authorizationServerMetadata(origin: string): {
88
+ issuer: string;
89
+ authorization_endpoint: string;
90
+ token_endpoint: string;
91
+ registration_endpoint: string;
92
+ response_types_supported: string[];
93
+ grant_types_supported: string[];
94
+ code_challenge_methods_supported: string[];
95
+ token_endpoint_auth_methods_supported: string[];
96
+ scopes_supported: ("read" | "solve")[];
97
+ client_id_metadata_document_supported: boolean;
98
+ authorization_response_iss_parameter_supported: boolean;
99
+ };
100
+ export declare function createOAuthServer(options: OAuthServerOptions): {
101
+ register: (input: unknown) => HttpResult;
102
+ resolveClient: (clientId: string) => Promise<OAuthClient>;
103
+ parseAuthorizeRequest: (query: URLSearchParams) => Promise<AuthorizeRequest>;
104
+ approve: (request: AuthorizeRequest, grant: Grant) => string;
105
+ deny: (request: AuthorizeRequest) => string;
106
+ exchange: (form: URLSearchParams) => HttpResult;
107
+ protectedResourceMetadata: () => {
108
+ resource: string;
109
+ authorization_servers: string[];
110
+ scopes_supported: ("read" | "solve")[];
111
+ bearer_methods_supported: string[];
112
+ };
113
+ authorizationServerMetadata: () => {
114
+ issuer: string;
115
+ authorization_endpoint: string;
116
+ token_endpoint: string;
117
+ registration_endpoint: string;
118
+ response_types_supported: string[];
119
+ grant_types_supported: string[];
120
+ code_challenge_methods_supported: string[];
121
+ token_endpoint_auth_methods_supported: string[];
122
+ scopes_supported: ("read" | "solve")[];
123
+ client_id_metadata_document_supported: boolean;
124
+ authorization_response_iss_parameter_supported: boolean;
125
+ };
126
+ };
127
+ export type OAuthServer = ReturnType<typeof createOAuthServer>;
128
+ /** OAuth scopes to the API scopes a minted token gets. */
129
+ export declare function apiScopesFor(scopes: readonly OAuthScope[]): string[];
130
+ /** A redirect to a program on the user's own machine, which any local process can claim. */
131
+ export declare function isLoopbackRedirect(uri: string): boolean;
132
+ /** Exact, except a loopback redirect matches on any port (RFC 8252 §7.3). */
133
+ export declare function redirectMatches(registered: string, requested: string): boolean;
134
+ export {};
135
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,415 @@
1
+ /**
2
+ * OAuth 2.1 for MCP clients, with this instance as its own authorization server.
3
+ *
4
+ * The access token is an ordinary API token. The host mints it while the user is
5
+ * signed in, at consent, through the same path as Settings → API tokens; this
6
+ * module seals the raw key into the authorization code and hands it over at the
7
+ * token endpoint. So `/mcp` and `/api/v1` keep one credential type.
8
+ *
9
+ * Nothing here is stored. A registered client's id is its own signed metadata,
10
+ * and a code is its own encrypted grant, bound to the issuing origin. The only
11
+ * state is the set of redeemed codes, in the host's memory, so on several
12
+ * replicas a code could be redeemed once per replica within its minute, and only
13
+ * by whoever holds the PKCE verifier.
14
+ */
15
+ import { createCipheriv, createDecipheriv, createHash, createHmac, hkdfSync, randomBytes, timingSafeEqual } from 'node:crypto';
16
+ /** The scopes a grant can carry. Each maps to one org-wide API scope. */
17
+ export const OAUTH_SCOPES = ['read', 'solve'];
18
+ export const MCP_PATH = '/mcp';
19
+ const CODE_TTL_MS = 60_000;
20
+ const CLIENT_NAME_MAX = 100;
21
+ const REDIRECT_URIS_MAX = 10;
22
+ const CIMD_TTL_MS = 60 * 60_000;
23
+ // A failing metadata URL is not refetched for this long: each fetch is outbound
24
+ // work an anonymous caller could otherwise trigger at will.
25
+ const CIMD_FAILURE_TTL_MS = 60_000;
26
+ const CIMD_CACHE_MAX = 500;
27
+ const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
28
+ export class OAuthError extends Error {
29
+ error;
30
+ status;
31
+ constructor(
32
+ /** RFC 6749 / 7591 error code. */
33
+ error, description, status = 400) {
34
+ super(description);
35
+ this.error = error;
36
+ this.status = status;
37
+ this.name = 'OAuthError';
38
+ }
39
+ toBody() {
40
+ return { error: this.error, error_description: this.message };
41
+ }
42
+ }
43
+ // ============================================================================
44
+ // Discovery documents
45
+ // ============================================================================
46
+ export function mcpResourceUrl(origin) {
47
+ return origin + MCP_PATH;
48
+ }
49
+ export function resourceMetadataUrl(origin) {
50
+ return `${origin}/.well-known/oauth-protected-resource${MCP_PATH}`;
51
+ }
52
+ /** RFC 9728. Claude uses only the first authorization server. */
53
+ export function protectedResourceMetadata(origin) {
54
+ return {
55
+ resource: mcpResourceUrl(origin),
56
+ authorization_servers: [origin],
57
+ scopes_supported: [...OAUTH_SCOPES],
58
+ bearer_methods_supported: ['header']
59
+ };
60
+ }
61
+ /**
62
+ * RFC 8414. Claude picks Client ID Metadata Documents only when both
63
+ * `client_id_metadata_document_supported` and the `none` auth method appear.
64
+ */
65
+ export function authorizationServerMetadata(origin) {
66
+ return {
67
+ issuer: origin,
68
+ authorization_endpoint: `${origin}/oauth/authorize`,
69
+ token_endpoint: `${origin}/oauth/token`,
70
+ registration_endpoint: `${origin}/oauth/register`,
71
+ response_types_supported: ['code'],
72
+ grant_types_supported: ['authorization_code'],
73
+ code_challenge_methods_supported: ['S256'],
74
+ token_endpoint_auth_methods_supported: ['none'],
75
+ scopes_supported: [...OAUTH_SCOPES],
76
+ client_id_metadata_document_supported: true,
77
+ authorization_response_iss_parameter_supported: true
78
+ };
79
+ }
80
+ // ============================================================================
81
+ // Server
82
+ // ============================================================================
83
+ export function createOAuthServer(options) {
84
+ const { origin } = options;
85
+ const now = options.now ?? Date.now;
86
+ const signKey = derive(options.secret, 'selva-oauth-client');
87
+ const codeKey = derive(options.secret, `selva-oauth-code:${origin}`);
88
+ const redeemed = options.redeemedCodes ?? new Map();
89
+ const metadataCache = new Map();
90
+ // ==========================================================================
91
+ // Clients
92
+ // ==========================================================================
93
+ /** RFC 7591. The client id carries the metadata, signed, so nothing is stored. */
94
+ function register(input) {
95
+ try {
96
+ const meta = (input ?? {});
97
+ const redirectUris = checkRedirectUris(meta.redirect_uris);
98
+ const name = typeof meta.client_name === 'string' ? meta.client_name.trim() : '';
99
+ const payload = b64(JSON.stringify({ n: name.slice(0, CLIENT_NAME_MAX), r: redirectUris, t: now() }));
100
+ const clientId = `dcr_${payload}.${sign(signKey, payload)}`;
101
+ return {
102
+ status: 201,
103
+ body: {
104
+ client_id: clientId,
105
+ client_id_issued_at: Math.floor(now() / 1000),
106
+ client_name: name || undefined,
107
+ redirect_uris: redirectUris,
108
+ grant_types: ['authorization_code'],
109
+ response_types: ['code'],
110
+ token_endpoint_auth_method: 'none'
111
+ }
112
+ };
113
+ }
114
+ catch (err) {
115
+ if (err instanceof OAuthError)
116
+ return { status: err.status, body: err.toBody() };
117
+ throw err;
118
+ }
119
+ }
120
+ async function resolveClient(clientId) {
121
+ if (clientId.startsWith('dcr_'))
122
+ return registeredClient(clientId);
123
+ if (clientId.startsWith('https://'))
124
+ return metadataClient(clientId);
125
+ throw new OAuthError('invalid_client', 'Unknown client.');
126
+ }
127
+ function registeredClient(clientId) {
128
+ const [payload, signature] = clientId.slice('dcr_'.length).split('.');
129
+ if (!payload || !signature || !safeEqual(signature, sign(signKey, payload))) {
130
+ throw new OAuthError('invalid_client', 'Unknown client.');
131
+ }
132
+ const meta = JSON.parse(unb64(payload));
133
+ return { clientId, name: meta.n || 'An MCP client', redirectUris: meta.r };
134
+ }
135
+ async function metadataClient(url) {
136
+ const cached = metadataCache.get(url);
137
+ if (cached) {
138
+ if ('client' in cached && now() - cached.at < CIMD_TTL_MS)
139
+ return cached.client;
140
+ if ('failure' in cached && now() - cached.at < CIMD_FAILURE_TTL_MS)
141
+ throw cached.failure;
142
+ }
143
+ if (!options.fetchClientMetadata) {
144
+ throw new OAuthError('invalid_client', 'This server does not accept URL client ids.');
145
+ }
146
+ try {
147
+ const client = await readMetadata(url, options.fetchClientMetadata);
148
+ remember(url, { at: now(), client });
149
+ return client;
150
+ }
151
+ catch (err) {
152
+ if (!(err instanceof OAuthError))
153
+ throw err;
154
+ remember(url, { at: now(), failure: err });
155
+ throw err;
156
+ }
157
+ }
158
+ function remember(url, entry) {
159
+ if (metadataCache.size >= CIMD_CACHE_MAX) {
160
+ metadataCache.delete(metadataCache.keys().next().value);
161
+ }
162
+ metadataCache.set(url, entry);
163
+ }
164
+ // ==========================================================================
165
+ // Authorization
166
+ // ==========================================================================
167
+ /**
168
+ * Validates the query `/oauth/authorize` arrives with. An `OAuthError` from a
169
+ * bad client or redirect URI must be shown, not redirected: the redirect target
170
+ * is exactly what can't be trusted.
171
+ */
172
+ async function parseAuthorizeRequest(query) {
173
+ const client = await resolveClient(query.get('client_id') ?? '');
174
+ const redirectUri = query.get('redirect_uri') ?? '';
175
+ if (!client.redirectUris.some((r) => redirectMatches(r, redirectUri))) {
176
+ throw new OAuthError('invalid_request', 'The redirect URI is not registered for this client.');
177
+ }
178
+ if (query.get('response_type') !== 'code') {
179
+ throw new OAuthError('unsupported_response_type', 'Only response_type=code is supported.');
180
+ }
181
+ const codeChallenge = query.get('code_challenge') ?? '';
182
+ if (!codeChallenge || query.get('code_challenge_method') !== 'S256') {
183
+ throw new OAuthError('invalid_request', 'PKCE with code_challenge_method=S256 is required.');
184
+ }
185
+ const resource = query.get('resource') ?? mcpResourceUrl(origin);
186
+ if (!isThisResource(resource)) {
187
+ throw new OAuthError('invalid_target', 'The resource is not this server.');
188
+ }
189
+ return {
190
+ client,
191
+ redirectUri,
192
+ state: query.get('state') ?? undefined,
193
+ codeChallenge,
194
+ scopes: parseScopes(query.get('scope')),
195
+ resource
196
+ };
197
+ }
198
+ /** Where to send the browser after consent: the client's redirect URI with a code. */
199
+ function approve(request, grant) {
200
+ const code = seal(codeKey, {
201
+ c: request.client.clientId,
202
+ r: request.redirectUri,
203
+ p: request.codeChallenge,
204
+ x: now() + CODE_TTL_MS,
205
+ g: grant
206
+ });
207
+ return withParams(request.redirectUri, { code, state: request.state, iss: origin });
208
+ }
209
+ function deny(request) {
210
+ return withParams(request.redirectUri, {
211
+ error: 'access_denied',
212
+ state: request.state,
213
+ iss: origin
214
+ });
215
+ }
216
+ // ==========================================================================
217
+ // Token endpoint
218
+ // ==========================================================================
219
+ function exchange(form) {
220
+ try {
221
+ if (form.get('grant_type') !== 'authorization_code') {
222
+ throw new OAuthError('unsupported_grant_type', 'Only authorization_code is supported.');
223
+ }
224
+ const code = form.get('code') ?? '';
225
+ const sealed = open(codeKey, code);
226
+ if (!sealed || sealed.x < now()) {
227
+ throw new OAuthError('invalid_grant', 'The code is invalid or expired.');
228
+ }
229
+ if (sealed.c !== form.get('client_id') || sealed.r !== form.get('redirect_uri')) {
230
+ throw new OAuthError('invalid_grant', 'The code was issued to another client.');
231
+ }
232
+ const verifier = form.get('code_verifier') ?? '';
233
+ if (!safeEqual(createHash('sha256').update(verifier).digest('base64url'), sealed.p)) {
234
+ throw new OAuthError('invalid_grant', 'The code_verifier does not match.');
235
+ }
236
+ const resource = form.get('resource');
237
+ if (resource !== null && !isThisResource(resource)) {
238
+ throw new OAuthError('invalid_target', 'The resource is not this server.');
239
+ }
240
+ if (!markRedeemed(code, sealed.x)) {
241
+ throw new OAuthError('invalid_grant', 'The code was already used.');
242
+ }
243
+ const { g } = sealed;
244
+ return {
245
+ status: 200,
246
+ body: {
247
+ access_token: g.secret,
248
+ token_type: 'Bearer',
249
+ expires_in: Math.max(0, Math.floor((Date.parse(g.expiresAt) - now()) / 1000)),
250
+ scope: g.scopes.join(' ')
251
+ }
252
+ };
253
+ }
254
+ catch (err) {
255
+ if (err instanceof OAuthError)
256
+ return { status: err.status, body: err.toBody() };
257
+ throw err;
258
+ }
259
+ }
260
+ function markRedeemed(code, expiresAt) {
261
+ const t = now();
262
+ for (const [k, x] of redeemed)
263
+ if (x < t)
264
+ redeemed.delete(k);
265
+ const id = createHash('sha256').update(code).digest('base64url');
266
+ if (redeemed.has(id))
267
+ return false;
268
+ redeemed.set(id, expiresAt);
269
+ return true;
270
+ }
271
+ function isThisResource(resource) {
272
+ const r = resource.replace(/\/$/, '');
273
+ return r === origin || r === mcpResourceUrl(origin);
274
+ }
275
+ return {
276
+ register,
277
+ resolveClient,
278
+ parseAuthorizeRequest,
279
+ approve,
280
+ deny,
281
+ exchange,
282
+ protectedResourceMetadata: () => protectedResourceMetadata(origin),
283
+ authorizationServerMetadata: () => authorizationServerMetadata(origin)
284
+ };
285
+ }
286
+ /** OAuth scopes to the API scopes a minted token gets. */
287
+ export function apiScopesFor(scopes) {
288
+ return scopes.map((s) => `${s}:all`);
289
+ }
290
+ // ============================================================================
291
+ // Helpers
292
+ // ============================================================================
293
+ async function readMetadata(url, fetchClientMetadata) {
294
+ let doc;
295
+ try {
296
+ doc = (await fetchClientMetadata(url));
297
+ }
298
+ catch {
299
+ throw new OAuthError('invalid_client', 'The client metadata document could not be read.');
300
+ }
301
+ if (doc?.client_id !== url) {
302
+ throw new OAuthError('invalid_client', 'The metadata document names a different client_id.');
303
+ }
304
+ return {
305
+ clientId: url,
306
+ name: typeof doc.client_name === 'string' && doc.client_name.trim()
307
+ ? doc.client_name.trim().slice(0, CLIENT_NAME_MAX)
308
+ : new URL(url).host,
309
+ redirectUris: checkRedirectUris(doc.redirect_uris)
310
+ };
311
+ }
312
+ /**
313
+ * Every scope when the client asks for none; unknown scopes are dropped. `read`
314
+ * is always in: `solve` includes it at /api/v1, and a grant without it is empty.
315
+ */
316
+ function parseScopes(raw) {
317
+ const asked = (raw ?? '').split(' ').filter(Boolean);
318
+ if (!OAUTH_SCOPES.some((s) => asked.includes(s)))
319
+ return [...OAUTH_SCOPES];
320
+ return OAUTH_SCOPES.filter((s) => s === 'read' || asked.includes(s));
321
+ }
322
+ function checkRedirectUris(value) {
323
+ if (!Array.isArray(value) || !value.length || value.length > REDIRECT_URIS_MAX) {
324
+ throw new OAuthError('invalid_redirect_uri', 'Give between 1 and 10 redirect_uris.');
325
+ }
326
+ for (const uri of value) {
327
+ if (typeof uri !== 'string' || !isAllowedRedirect(uri)) {
328
+ throw new OAuthError('invalid_redirect_uri', 'Redirect URIs must be https, or http on a loopback address.');
329
+ }
330
+ }
331
+ return value;
332
+ }
333
+ function isAllowedRedirect(uri) {
334
+ let url;
335
+ try {
336
+ url = new URL(uri);
337
+ }
338
+ catch {
339
+ return false;
340
+ }
341
+ if (url.hash)
342
+ return false;
343
+ return (url.protocol === 'https:' || (url.protocol === 'http:' && LOOPBACK_HOSTS.has(url.hostname)));
344
+ }
345
+ /** A redirect to a program on the user's own machine, which any local process can claim. */
346
+ export function isLoopbackRedirect(uri) {
347
+ try {
348
+ return LOOPBACK_HOSTS.has(new URL(uri).hostname);
349
+ }
350
+ catch {
351
+ return false;
352
+ }
353
+ }
354
+ /** Exact, except a loopback redirect matches on any port (RFC 8252 §7.3). */
355
+ export function redirectMatches(registered, requested) {
356
+ if (registered === requested)
357
+ return true;
358
+ let a, b;
359
+ try {
360
+ a = new URL(registered);
361
+ b = new URL(requested);
362
+ }
363
+ catch {
364
+ return false;
365
+ }
366
+ return (a.protocol === 'http:' &&
367
+ b.protocol === 'http:' &&
368
+ LOOPBACK_HOSTS.has(a.hostname) &&
369
+ a.hostname === b.hostname &&
370
+ a.pathname === b.pathname &&
371
+ a.search === b.search);
372
+ }
373
+ function withParams(uri, params) {
374
+ const url = new URL(uri);
375
+ for (const [k, v] of Object.entries(params))
376
+ if (v !== undefined)
377
+ url.searchParams.set(k, v);
378
+ return url.toString();
379
+ }
380
+ function derive(secret, info) {
381
+ return Buffer.from(hkdfSync('sha256', secret, '', info, 32));
382
+ }
383
+ function sign(key, data) {
384
+ return createHmac('sha256', key).update(data).digest('base64url');
385
+ }
386
+ function seal(key, value) {
387
+ const iv = randomBytes(12);
388
+ const cipher = createCipheriv('aes-256-gcm', key, iv);
389
+ const body = Buffer.concat([cipher.update(JSON.stringify(value)), cipher.final()]);
390
+ return Buffer.concat([iv, cipher.getAuthTag(), body]).toString('base64url');
391
+ }
392
+ function open(key, sealed) {
393
+ try {
394
+ const raw = Buffer.from(sealed, 'base64url');
395
+ const decipher = createDecipheriv('aes-256-gcm', key, raw.subarray(0, 12));
396
+ decipher.setAuthTag(raw.subarray(12, 28));
397
+ const body = Buffer.concat([decipher.update(raw.subarray(28)), decipher.final()]);
398
+ return JSON.parse(body.toString('utf8'));
399
+ }
400
+ catch {
401
+ return null;
402
+ }
403
+ }
404
+ function b64(text) {
405
+ return Buffer.from(text).toString('base64url');
406
+ }
407
+ function unb64(text) {
408
+ return Buffer.from(text, 'base64url').toString('utf8');
409
+ }
410
+ function safeEqual(a, b) {
411
+ const x = Buffer.from(a);
412
+ const y = Buffer.from(b);
413
+ return x.length === y.length && timingSafeEqual(x, y);
414
+ }
415
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selvajs/server",
3
- "version": "1.5.0-beta.6",
3
+ "version": "1.5.0-beta.7",
4
4
  "description": "Transport-agnostic server building blocks for apps built on the Selva engine (limits, rate limiting, SSRF guard, remote-definition fetch, definition service + render loader); the solve core lives in @selvajs/solve/server",
5
5
  "license": "MIT",
6
6
  "author": "VektorNode",
@@ -41,6 +41,11 @@
41
41
  "types": "./dist/providers/index.d.ts",
42
42
  "import": "./dist/providers/index.js"
43
43
  },
44
+ "./oauth": {
45
+ "selva-source": "./src/oauth/index.ts",
46
+ "types": "./dist/oauth/index.d.ts",
47
+ "import": "./dist/oauth/index.js"
48
+ },
44
49
  "./tokens": {
45
50
  "selva-source": "./src/tokens/index.ts",
46
51
  "types": "./dist/tokens/index.d.ts",
@@ -111,8 +116,8 @@
111
116
  "dependencies": {
112
117
  "zod": "^4.6.5",
113
118
  "@selvajs/compute": "^4.2.2-beta.0",
114
- "@selvajs/platform": "^0.21.0-beta.2",
115
119
  "@selvajs/notifications": "^0.3.0-beta.2",
120
+ "@selvajs/platform": "^0.21.0-beta.2",
116
121
  "@selvajs/schemas": "^5.2.0"
117
122
  },
118
123
  "peerDependencies": {