@every-app/sdk 0.3.0-rc.1 → 0.3.0-rc.10
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/LICENSE +21 -0
- package/README.md +1 -1
- package/dist/cloudflare/catalogSettings.generated.d.ts +81 -0
- package/dist/cloudflare/catalogSettings.generated.d.ts.map +1 -0
- package/dist/cloudflare/catalogSettings.generated.js +174 -0
- package/dist/cloudflare/index.d.ts +3 -2
- package/dist/cloudflare/index.d.ts.map +1 -1
- package/dist/cloudflare/index.js +4 -1
- package/dist/cloudflare/sentinel.d.ts +60 -2
- package/dist/cloudflare/sentinel.d.ts.map +1 -1
- package/dist/cloudflare/sentinel.js +37 -2
- package/dist/cloudflare/worker.d.ts +357 -63
- package/dist/cloudflare/worker.d.ts.map +1 -1
- package/dist/cloudflare/worker.js +363 -104
- package/dist/dev/index.d.ts +1 -1
- package/dist/dev/index.d.ts.map +1 -1
- package/dist/dev/index.js +1 -1
- package/dist/dev/keypair.d.ts +2 -0
- package/dist/dev/keypair.d.ts.map +1 -1
- package/dist/dev/keypair.js +2 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/internal/aiDefault.d.ts +204 -0
- package/dist/internal/aiDefault.d.ts.map +1 -0
- package/dist/internal/aiDefault.js +334 -0
- package/dist/internal/aiProviders.d.ts +7 -2
- package/dist/internal/aiProviders.d.ts.map +1 -1
- package/dist/internal/aiProviders.js +17 -4
- package/dist/internal/appSettings.d.ts +82 -4
- package/dist/internal/appSettings.d.ts.map +1 -1
- package/dist/internal/appSettings.js +204 -29
- package/dist/internal/audit.d.ts +108 -0
- package/dist/internal/audit.d.ts.map +1 -0
- package/dist/internal/audit.js +235 -0
- package/dist/internal/capabilities.d.ts +2268 -438
- package/dist/internal/capabilities.d.ts.map +1 -1
- package/dist/internal/capabilities.js +128 -539
- package/dist/internal/catalog/commerce.d.ts +394 -0
- package/dist/internal/catalog/commerce.d.ts.map +1 -0
- package/dist/internal/catalog/commerce.js +477 -0
- package/dist/internal/catalog/comms.d.ts +375 -0
- package/dist/internal/catalog/comms.d.ts.map +1 -0
- package/dist/internal/catalog/comms.js +520 -0
- package/dist/internal/catalog/index.d.ts +1973 -0
- package/dist/internal/catalog/index.d.ts.map +1 -0
- package/dist/internal/catalog/index.js +19 -0
- package/dist/internal/catalog/inference.d.ts +393 -0
- package/dist/internal/catalog/inference.d.ts.map +1 -0
- package/dist/internal/catalog/inference.js +460 -0
- package/dist/internal/catalog/infra.d.ts +423 -0
- package/dist/internal/catalog/infra.d.ts.map +1 -0
- package/dist/internal/catalog/infra.js +543 -0
- package/dist/internal/catalog/search.d.ts +400 -0
- package/dist/internal/catalog/search.d.ts.map +1 -0
- package/dist/internal/catalog/search.js +463 -0
- package/dist/internal/devProviders.d.ts +2 -2
- package/dist/internal/devProviders.d.ts.map +1 -1
- package/dist/internal/devProviders.js +19 -1
- package/dist/internal/events.d.ts +13 -2
- package/dist/internal/events.d.ts.map +1 -1
- package/dist/internal/events.js +47 -4
- package/dist/internal/gatewaySettings.d.ts +3 -2
- package/dist/internal/gatewaySettings.d.ts.map +1 -1
- package/dist/internal/gatewaySettings.js +12 -6
- package/dist/internal/identity.d.ts +41 -4
- package/dist/internal/identity.d.ts.map +1 -1
- package/dist/internal/identity.js +48 -10
- package/dist/internal/index.d.ts +6 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +6 -1
- package/dist/internal/members.d.ts +3 -2
- package/dist/internal/members.d.ts.map +1 -1
- package/dist/internal/oauthClient.d.ts +10 -12
- package/dist/internal/oauthClient.d.ts.map +1 -1
- package/dist/internal/oauthClient.js +20 -81
- package/dist/internal/oauthPresets.d.ts +33 -0
- package/dist/internal/oauthPresets.d.ts.map +1 -0
- package/dist/internal/oauthPresets.js +1064 -0
- package/dist/internal/oauthScopes.d.ts +56 -1
- package/dist/internal/oauthScopes.d.ts.map +1 -1
- package/dist/internal/oauthScopes.js +98 -4
- package/dist/internal/oauthSpec.d.ts +102 -0
- package/dist/internal/oauthSpec.d.ts.map +1 -0
- package/dist/internal/oauthSpec.js +789 -0
- package/dist/internal/protocol.d.ts +64 -1
- package/dist/internal/protocol.d.ts.map +1 -1
- package/dist/internal/protocol.js +51 -1
- package/dist/internal/providerRegistry.d.ts +77 -6
- package/dist/internal/providerRegistry.d.ts.map +1 -1
- package/dist/internal/providerRegistry.js +178 -8
- package/dist/internal/providerSpec.d.ts +18 -7
- package/dist/internal/providerSpec.d.ts.map +1 -1
- package/dist/internal/providerSpec.js +442 -34
- package/dist/internal/signInProviders.d.ts +104 -0
- package/dist/internal/signInProviders.d.ts.map +1 -0
- package/dist/internal/signInProviders.js +245 -0
- package/dist/manifest.d.ts +238 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +30 -0
- package/dist/server/ai.d.ts +111 -0
- package/dist/server/ai.d.ts.map +1 -0
- package/dist/server/ai.js +145 -0
- package/dist/server/aiBinding.d.ts +68 -0
- package/dist/server/aiBinding.d.ts.map +1 -0
- package/dist/server/aiBinding.js +294 -0
- package/dist/server/attribution.d.ts +9 -5
- package/dist/server/attribution.d.ts.map +1 -1
- package/dist/server/attribution.js +12 -4
- package/dist/server/authorizeUrl.d.ts +1 -1
- package/dist/server/authorizeUrl.d.ts.map +1 -1
- package/dist/server/authorizeUrl.js +2 -6
- package/dist/server/connectUrl.d.ts +21 -0
- package/dist/server/connectUrl.d.ts.map +1 -0
- package/dist/server/connectUrl.js +37 -0
- package/dist/server/context.d.ts +68 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +117 -0
- package/dist/server/emailBinding.d.ts +72 -0
- package/dist/server/emailBinding.d.ts.map +1 -0
- package/dist/server/emailBinding.js +124 -0
- package/dist/server/emit.d.ts +1 -1
- package/dist/server/emit.d.ts.map +1 -1
- package/dist/server/emit.js +7 -7
- package/dist/server/env.d.ts +44 -0
- package/dist/server/env.d.ts.map +1 -0
- package/dist/server/env.js +1 -0
- package/dist/server/everyApp.d.ts +27 -7
- package/dist/server/everyApp.d.ts.map +1 -1
- package/dist/server/everyApp.js +106 -5
- package/dist/server/fromMcpTools.d.ts +89 -0
- package/dist/server/fromMcpTools.d.ts.map +1 -0
- package/dist/server/fromMcpTools.js +192 -0
- package/dist/server/gatewayFetch.d.ts +42 -18
- package/dist/server/gatewayFetch.d.ts.map +1 -1
- package/dist/server/gatewayFetch.js +138 -19
- package/dist/server/gatewayUrl.d.ts +13 -0
- package/dist/server/gatewayUrl.d.ts.map +1 -0
- package/dist/server/gatewayUrl.js +34 -0
- package/dist/server/index.d.ts +15 -4
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +12 -2
- package/dist/server/integrationFetch.d.ts +70 -39
- package/dist/server/integrationFetch.d.ts.map +1 -1
- package/dist/server/integrationFetch.js +244 -82
- package/dist/server/listMembers.d.ts +1 -1
- package/dist/server/listMembers.d.ts.map +1 -1
- package/dist/server/listMembers.js +8 -11
- package/dist/server/refusal.d.ts +55 -0
- package/dist/server/refusal.d.ts.map +1 -0
- package/dist/server/refusal.js +193 -0
- package/dist/server/sendEmail.d.ts +1 -1
- package/dist/server/sendEmail.d.ts.map +1 -1
- package/dist/server/sendEmail.js +7 -7
- package/dist/server/toolsEndpoint.d.ts.map +1 -1
- package/dist/server/toolsEndpoint.js +11 -5
- package/dist/tanstack-start/index.d.ts +9 -0
- package/dist/tanstack-start/index.d.ts.map +1 -0
- package/dist/tanstack-start/index.js +29 -0
- package/dist/testing/index.d.ts +93 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +156 -0
- package/package.json +35 -14
|
@@ -24,7 +24,8 @@ export declare const GATEWAY_OWN_SETTINGS: readonly ["AI_PROXY_EXTRA_ROUTES", "E
|
|
|
24
24
|
export type SettableGatewaySetting = Exclude<CapabilitySecret, (typeof INSTALL_OWNED_GATEWAY_SETTINGS)[number]> | (typeof GATEWAY_OWN_SETTINGS)[number];
|
|
25
25
|
/**
|
|
26
26
|
* The Gateway's optional settings `everyapp secret set` changes: every
|
|
27
|
-
* setting a catalog provider reads,
|
|
27
|
+
* setting a catalog provider reads, the Gateway's own, then the sign-in
|
|
28
|
+
* providers' (`<ID>_SIGNIN_<FIELD>`, ./signInProviders.ts).
|
|
28
29
|
*/
|
|
29
30
|
export declare const SETTABLE_GATEWAY_SETTINGS: readonly SettableGatewaySetting[];
|
|
30
31
|
/**
|
|
@@ -51,7 +52,7 @@ export declare function isSettableGatewaySetting(name: string): boolean;
|
|
|
51
52
|
* are typed and check their shape; anything else is a credential and
|
|
52
53
|
* stays hidden.
|
|
53
54
|
*/
|
|
54
|
-
export declare const PLAIN_GATEWAY_SETTINGS: readonly ["EMAIL_FROM", "EMAIL_FROM_NAME", "EMAIL_PROVIDER", "EMAIL_PASSWORD_SIGN_IN", "
|
|
55
|
+
export declare const PLAIN_GATEWAY_SETTINGS: readonly ["EMAIL_FROM", "EMAIL_FROM_NAME", "EMAIL_PROVIDER", "EMAIL_PASSWORD_SIGN_IN", "AI_PROXY_EXTRA_ROUTES", "MCP_OAUTH_ENABLED", "MCP_DCR_ENABLED", "MCP_ALLOWED_ORIGINS", "MCP_AUDIT_RETENTION_DAYS", "CLOUDFLARE_ACCESS_OIDC_ISSUER", "CLOUDFLARE_ACCESS_OIDC_CLIENT_ID", "CLOUDFLARE_ACCESS_OIDC_LABEL", "CLOUDFLARE_ACCESS_TEAM_DOMAIN", "CLOUDFLARE_ACCESS_AUD", "CLOUDFLARE_ACCESS_APPS_AUD", "CLOUDFLARE_ACCESS_AUTO_JOIN_DOMAINS", "CLOUDFLARE_ACCESS_OUTER_RING_AUTO_JOIN", "HOSTED_OPEN_SIGNUP", "BROWSER_APP_INSTALLS", "DISPATCH_NAMESPACE", "THIRD_PARTY_DOMAIN", "EVENTS_ALLOW_PRIVATE_TARGETS"];
|
|
55
56
|
/** Whether a settable Gateway setting's value is a plain value, not a credential. */
|
|
56
57
|
export declare function isPlainGatewaySetting(name: string): boolean;
|
|
57
58
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gatewaySettings.d.ts","sourceRoot":"","sources":["../../src/internal/gatewaySettings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"gatewaySettings.d.ts","sourceRoot":"","sources":["../../src/internal/gatewaySettings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAM3B;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,mLASjC,CAAC;AAMX,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElE;AAmBD,mGAAmG;AACnG,eAAO,MAAM,oBAAoB,yrBAkCvB,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAC9B,OAAO,CAAC,gBAAgB,EAAE,CAAC,OAAO,8BAA8B,CAAC,CAAC,MAAM,CAAC,CAAC,GAC1E,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,sBAAsB,EAItE,CAAC;AAIF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,QAAgC,CAAC;AAEvE,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,olBAuBmB,CAAC;AASvD,qFAAqF;AACrF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,6EAIa,CAAC;AAIvD,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED,iGAAiG;AACjG,eAAO,MAAM,yBAAyB,yDAI5B,CAAC;AAEX,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAmBD,iDAAiD;AACjD,eAAO,MAAM,8BAA8B,sFAC0C,CAAC;AAEtF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAM7D;AAED,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAQ5E"}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* declaring every settable one.
|
|
12
12
|
*/
|
|
13
13
|
import { CAPABILITIES, CAPABILITY_IDS, capabilitySettings, } from "./capabilities.js";
|
|
14
|
+
import { PLAIN_SIGN_IN_SETTINGS, SIGN_IN_GATEWAY_SETTINGS, } from "./signInProviders.js";
|
|
14
15
|
/**
|
|
15
16
|
* The Gateway's own settings: the install writes them once (`everyapp
|
|
16
17
|
* setup`), or an operator by hand (THIRD_PARTY_DEPLOYS), and `everyapp
|
|
@@ -33,8 +34,7 @@ export function isInstallOwnedGatewaySetting(name) {
|
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
35
36
|
* The settings the catalog's providers read (the AI providers' keys, the
|
|
36
|
-
* API-key providers' keys, the OAuth clients
|
|
37
|
-
* URL), in catalog order, the install's own left out: what `everyapp
|
|
37
|
+
* API-key providers' keys and hosts, the OAuth clients), in catalog order, the install's own left out: what `everyapp
|
|
38
38
|
* secret set` accepts because a provider reads it. A gateway's registered
|
|
39
39
|
* rows add theirs at run time (providerRegistry.settingNames()).
|
|
40
40
|
*/
|
|
@@ -75,7 +75,7 @@ export const GATEWAY_OWN_SETTINGS = [
|
|
|
75
75
|
// gate, THIRD_PARTY_DEPLOYS, is never set from here: it is opened by
|
|
76
76
|
// hand once the launch checks pass (docs/runbooks/hosted-install.md).
|
|
77
77
|
"CF_DEPLOY_TOKEN",
|
|
78
|
-
// Self-hosted
|
|
78
|
+
// Self-hosted Gateway app installs: off unless exactly "on" (everyapp deploy-token add).
|
|
79
79
|
"BROWSER_APP_INSTALLS",
|
|
80
80
|
"DISPATCH_NAMESPACE",
|
|
81
81
|
"THIRD_PARTY_DOMAIN",
|
|
@@ -84,11 +84,13 @@ export const GATEWAY_OWN_SETTINGS = [
|
|
|
84
84
|
];
|
|
85
85
|
/**
|
|
86
86
|
* The Gateway's optional settings `everyapp secret set` changes: every
|
|
87
|
-
* setting a catalog provider reads,
|
|
87
|
+
* setting a catalog provider reads, the Gateway's own, then the sign-in
|
|
88
|
+
* providers' (`<ID>_SIGNIN_<FIELD>`, ./signInProviders.ts).
|
|
88
89
|
*/
|
|
89
90
|
export const SETTABLE_GATEWAY_SETTINGS = [
|
|
90
91
|
...PROVIDER_GATEWAY_SETTINGS,
|
|
91
92
|
...GATEWAY_OWN_SETTINGS,
|
|
93
|
+
...SIGN_IN_GATEWAY_SETTINGS,
|
|
92
94
|
];
|
|
93
95
|
const SETTABLE = new Set(SETTABLE_GATEWAY_SETTINGS);
|
|
94
96
|
/**
|
|
@@ -124,7 +126,6 @@ export const PLAIN_GATEWAY_SETTINGS = [
|
|
|
124
126
|
"EMAIL_FROM_NAME",
|
|
125
127
|
"EMAIL_PROVIDER",
|
|
126
128
|
"EMAIL_PASSWORD_SIGN_IN",
|
|
127
|
-
"MASTODON_URL",
|
|
128
129
|
"AI_PROXY_EXTRA_ROUTES",
|
|
129
130
|
"MCP_OAUTH_ENABLED",
|
|
130
131
|
"MCP_DCR_ENABLED",
|
|
@@ -144,7 +145,12 @@ export const PLAIN_GATEWAY_SETTINGS = [
|
|
|
144
145
|
"THIRD_PARTY_DOMAIN",
|
|
145
146
|
"EVENTS_ALLOW_PRIVATE_TARGETS",
|
|
146
147
|
];
|
|
147
|
-
const PLAIN = new Set(
|
|
148
|
+
const PLAIN = new Set([
|
|
149
|
+
...PLAIN_GATEWAY_SETTINGS,
|
|
150
|
+
// The sign-in providers' ids, issuer, label and tenant; their client
|
|
151
|
+
// secrets are credentials.
|
|
152
|
+
...PLAIN_SIGN_IN_SETTINGS,
|
|
153
|
+
]);
|
|
148
154
|
/** Whether a settable Gateway setting's value is a plain value, not a credential. */
|
|
149
155
|
export function isPlainGatewaySetting(name) {
|
|
150
156
|
return PLAIN.has(name);
|
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
import { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, type EveryAppUser, type IdentityChannel, type SystemClaims, type SystemTokenPurpose } from "./protocol.js";
|
|
2
|
-
export { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, type EveryAppUser, type IdentityChannel, };
|
|
1
|
+
import { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, ORG_ID_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, type EveryAppUser, type IdentityChannel, type SystemClaims, type SystemTokenPurpose } from "./protocol.js";
|
|
2
|
+
export { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, ORG_ID_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, type EveryAppUser, type IdentityChannel, };
|
|
3
3
|
export declare class IdentityError extends Error {
|
|
4
4
|
readonly status = 401;
|
|
5
5
|
constructor(message: string);
|
|
6
6
|
}
|
|
7
7
|
export declare class ConfigurationError extends Error {
|
|
8
8
|
readonly status = 500;
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* The Gateway refusal code the same gap gets once deployed
|
|
11
|
+
* (`ai_provider_not_configured`, `ai_default_not_configured`), when the
|
|
12
|
+
* error is "not set up" rather than a mistake in the code.
|
|
13
|
+
*/
|
|
14
|
+
readonly code: string | undefined;
|
|
15
|
+
/** The settings that would close the gap (`.dev.vars` names in local dev). */
|
|
16
|
+
readonly settings: readonly string[];
|
|
17
|
+
constructor(message: string, setup?: {
|
|
18
|
+
code: string;
|
|
19
|
+
settings?: readonly string[];
|
|
20
|
+
});
|
|
10
21
|
}
|
|
11
22
|
/**
|
|
12
23
|
* Parse the public key set from an env var value. Accepts a JSON array of PEM
|
|
@@ -35,6 +46,25 @@ export interface VerifyOptions {
|
|
|
35
46
|
* claims).
|
|
36
47
|
*/
|
|
37
48
|
export declare function verifyIdentityJwt(token: string, options: VerifyOptions): Promise<EveryAppUser>;
|
|
49
|
+
/** A verified identity, with when it stops being one. */
|
|
50
|
+
export interface VerifiedIdentity {
|
|
51
|
+
user: EveryAppUser;
|
|
52
|
+
/** The token's `exp`, in epoch milliseconds. */
|
|
53
|
+
expiresAt: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* {@link verifyIdentityJwt}, keeping the token's expiry: the SDK's request
|
|
57
|
+
* context stops forwarding an identity shortly before it, and goes on as
|
|
58
|
+
* the organization's background work.
|
|
59
|
+
*/
|
|
60
|
+
export declare function verifyIdentity(token: string, options: VerifyOptions): Promise<VerifiedIdentity>;
|
|
61
|
+
/**
|
|
62
|
+
* The organization pin: a deployed Worker serves one organization
|
|
63
|
+
* (`EVERY_APP_ORG_ID`), and an identity for any other is refused, whatever
|
|
64
|
+
* its audience says. Throws {@link IdentityError} on a mismatch; a Worker
|
|
65
|
+
* with no pin (a shared app's) accepts every organization.
|
|
66
|
+
*/
|
|
67
|
+
export declare function assertOrganizationPin(user: EveryAppUser, organizationId: string | undefined): void;
|
|
38
68
|
/**
|
|
39
69
|
* Verify the gateway's system token (the value of `x-everyapp-system`)
|
|
40
70
|
* fail-closed, for exactly one purpose. A user identity or public marker is
|
|
@@ -56,9 +86,16 @@ export interface IdentityResult {
|
|
|
56
86
|
user: EveryAppUser | null;
|
|
57
87
|
/** True when the gateway marked this request as a public route. */
|
|
58
88
|
isPublic: boolean;
|
|
89
|
+
/** When the identity expires (epoch ms); null on a public route. */
|
|
90
|
+
expiresAt: number | null;
|
|
59
91
|
}
|
|
60
92
|
export interface RequestIdentityOptions {
|
|
61
93
|
audience: string;
|
|
94
|
+
/**
|
|
95
|
+
* The organization this Worker is pinned to ({@link ORG_ID_ENV}): an
|
|
96
|
+
* identity for another is refused. Undefined accepts every organization.
|
|
97
|
+
*/
|
|
98
|
+
organizationId?: string;
|
|
62
99
|
/** Provide keys directly, or let {@link getIdentityFromRequest} read env. */
|
|
63
100
|
publicKeys?: string[];
|
|
64
101
|
/** Env bag to read {@link PUBLIC_KEYS_ENV} / {@link DEV_ENV} from. */
|
|
@@ -84,5 +121,5 @@ export declare function resolveVerifyOptions(options: RequestIdentityOptions): V
|
|
|
84
121
|
* problem — including a bare/forged public header — so a re-exposed worker
|
|
85
122
|
* fails closed.
|
|
86
123
|
*/
|
|
87
|
-
export declare function getIdentityFromRequest(request: Request, options: RequestIdentityOptions): Promise<IdentityResult>;
|
|
124
|
+
export declare function getIdentityFromRequest(request: Request | Headers, options: RequestIdentityOptions): Promise<IdentityResult>;
|
|
88
125
|
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/internal/identity.ts"],"names":[],"mappings":"AAgBA,OAAO,EACL,UAAU,EACV,OAAO,EACP,UAAU,EACV,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,UAAU,EACV,aAAa,EACb,eAAe,EACf,iBAAiB,EAKjB,KAAK,YAAY,EACjB,KAAK,eAAe,EAEpB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,UAAU,EACV,OAAO,EACP,UAAU,EACV,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,UAAU,EACV,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,CAAC;AAEF,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,MAAM,OAAO;gBACV,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,OAAO;
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/internal/identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* survives verification produces a user.
|
|
10
10
|
*/
|
|
11
11
|
import { importSPKI, jwtVerify, decodeProtectedHeader, } from "jose";
|
|
12
|
-
import { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, assertPublicMarkerClaims, assertSystemClaims, identityClaimsToEveryAppUser, ProtocolClaimsError, } from "./protocol.js";
|
|
13
|
-
export { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, };
|
|
12
|
+
import { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, ORG_ID_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, assertPublicMarkerClaims, assertSystemClaims, identityClaimsToEveryAppUser, ProtocolClaimsError, } from "./protocol.js";
|
|
13
|
+
export { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, ORG_ID_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, };
|
|
14
14
|
export class IdentityError extends Error {
|
|
15
15
|
status = 401;
|
|
16
16
|
constructor(message) {
|
|
@@ -20,9 +20,19 @@ export class IdentityError extends Error {
|
|
|
20
20
|
}
|
|
21
21
|
export class ConfigurationError extends Error {
|
|
22
22
|
status = 500;
|
|
23
|
-
|
|
23
|
+
/**
|
|
24
|
+
* The Gateway refusal code the same gap gets once deployed
|
|
25
|
+
* (`ai_provider_not_configured`, `ai_default_not_configured`), when the
|
|
26
|
+
* error is "not set up" rather than a mistake in the code.
|
|
27
|
+
*/
|
|
28
|
+
code;
|
|
29
|
+
/** The settings that would close the gap (`.dev.vars` names in local dev). */
|
|
30
|
+
settings;
|
|
31
|
+
constructor(message, setup) {
|
|
24
32
|
super(message);
|
|
25
33
|
this.name = "ConfigurationError";
|
|
34
|
+
this.code = setup?.code;
|
|
35
|
+
this.settings = setup?.settings ?? [];
|
|
26
36
|
}
|
|
27
37
|
}
|
|
28
38
|
/**
|
|
@@ -81,9 +91,19 @@ function assertDevIssuer(options) {
|
|
|
81
91
|
* claims).
|
|
82
92
|
*/
|
|
83
93
|
export async function verifyIdentityJwt(token, options) {
|
|
94
|
+
return (await verifyIdentity(token, options)).user;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* {@link verifyIdentityJwt}, keeping the token's expiry: the SDK's request
|
|
98
|
+
* context stops forwarding an identity shortly before it, and goes on as
|
|
99
|
+
* the organization's background work.
|
|
100
|
+
*/
|
|
101
|
+
export async function verifyIdentity(token, options) {
|
|
84
102
|
const payload = await verifyPinnedJwt(token, options, "user");
|
|
85
103
|
try {
|
|
86
|
-
|
|
104
|
+
const user = identityClaimsToEveryAppUser(payload);
|
|
105
|
+
// `exp` is a required claim (verifyPinnedJwt); jose checked it.
|
|
106
|
+
return { user, expiresAt: payload.exp * 1000 };
|
|
87
107
|
}
|
|
88
108
|
catch (error) {
|
|
89
109
|
if (error instanceof ProtocolClaimsError) {
|
|
@@ -92,6 +112,17 @@ export async function verifyIdentityJwt(token, options) {
|
|
|
92
112
|
throw error;
|
|
93
113
|
}
|
|
94
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* The organization pin: a deployed Worker serves one organization
|
|
117
|
+
* (`EVERY_APP_ORG_ID`), and an identity for any other is refused, whatever
|
|
118
|
+
* its audience says. Throws {@link IdentityError} on a mismatch; a Worker
|
|
119
|
+
* with no pin (a shared app's) accepts every organization.
|
|
120
|
+
*/
|
|
121
|
+
export function assertOrganizationPin(user, organizationId) {
|
|
122
|
+
if (organizationId && user.orgId !== organizationId) {
|
|
123
|
+
throw new IdentityError(`identity is for organization "${user.orgId}", and this Worker serves organization "${organizationId}" (${ORG_ID_ENV})`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
95
126
|
/**
|
|
96
127
|
* Verify the gateway's system token (the value of `x-everyapp-system`)
|
|
97
128
|
* fail-closed, for exactly one purpose. A user identity or public marker is
|
|
@@ -137,7 +168,7 @@ async function verifyPinnedJwt(token, options, expectedTyp) {
|
|
|
137
168
|
throw new IdentityError(`unexpected kid "${header.kid}"`);
|
|
138
169
|
}
|
|
139
170
|
if (expectedTyp !== "public" && !options.issuer) {
|
|
140
|
-
throw new IdentityError(`${ISSUER_ENV} not configured — deploy with the
|
|
171
|
+
throw new IdentityError(`${ISSUER_ENV} not configured — deploy with the EveryApp CLI or provide an explicit issuer.`);
|
|
141
172
|
}
|
|
142
173
|
const verifyOpts = {
|
|
143
174
|
algorithms: [IDENTITY_ALG],
|
|
@@ -217,15 +248,22 @@ export function resolveVerifyOptions(options) {
|
|
|
217
248
|
*/
|
|
218
249
|
export async function getIdentityFromRequest(request, options) {
|
|
219
250
|
const verifyOptions = resolveVerifyOptions(options);
|
|
220
|
-
const
|
|
251
|
+
const headers = isRequestLike(request) ? request.headers : request;
|
|
252
|
+
const publicMarker = headers.get(PUBLIC_HEADER);
|
|
221
253
|
if (publicMarker) {
|
|
222
254
|
await verifyPublicMarkerJwt(publicMarker, verifyOptions);
|
|
223
|
-
return { user: null, isPublic: true };
|
|
255
|
+
return { user: null, isPublic: true, expiresAt: null };
|
|
224
256
|
}
|
|
225
|
-
const token =
|
|
257
|
+
const token = headers.get(IDENTITY_HEADER);
|
|
226
258
|
if (!token) {
|
|
227
259
|
throw new IdentityError("request reached the app without an identity token (not proxied through the gateway?)");
|
|
228
260
|
}
|
|
229
|
-
const user = await
|
|
230
|
-
|
|
261
|
+
const { user, expiresAt } = await verifyIdentity(token, verifyOptions);
|
|
262
|
+
assertOrganizationPin(user, options.organizationId);
|
|
263
|
+
return { user, isPublic: false, expiresAt };
|
|
264
|
+
}
|
|
265
|
+
// Duck-typed: a Request from another realm (a test runner, a polyfill) still
|
|
266
|
+
// carries its headers the same way.
|
|
267
|
+
function isRequestLike(value) {
|
|
268
|
+
return "headers" in value && typeof value.headers?.get === "function";
|
|
231
269
|
}
|
package/dist/internal/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./protocol.js";
|
|
|
2
2
|
export * from "./tools.js";
|
|
3
3
|
export * from "./capabilities.js";
|
|
4
4
|
export * from "./aiProviders.js";
|
|
5
|
+
export * from "./aiDefault.js";
|
|
5
6
|
export * from "./gatewaySettings.js";
|
|
6
7
|
export * from "./appSettings.js";
|
|
7
8
|
export * from "./email.js";
|
|
@@ -9,11 +10,15 @@ export * from "./members.js";
|
|
|
9
10
|
export * from "./organizationName.js";
|
|
10
11
|
export * from "./oauthClient.js";
|
|
11
12
|
export * from "./oauthScopes.js";
|
|
13
|
+
export * from "./oauthSpec.js";
|
|
14
|
+
export * from "./oauthPresets.js";
|
|
12
15
|
export * from "./providerApps.js";
|
|
13
16
|
export * from "./events.js";
|
|
17
|
+
export * from "./audit.js";
|
|
14
18
|
export * from "./providerSpec.js";
|
|
15
19
|
export * from "./providerRegistry.js";
|
|
16
20
|
export * from "./remoteMcp.js";
|
|
21
|
+
export * from "./signInProviders.js";
|
|
17
22
|
export * from "./devProviders.js";
|
|
18
|
-
export { ConfigurationError, IdentityError, getIdentityFromRequest, parsePublicKeys, resolveVerifyOptions, verifyIdentityJwt, verifyPublicMarkerJwt, verifySystemJwt, type IdentityResult, type RequestIdentityOptions, type VerifyOptions, } from "./identity.js";
|
|
23
|
+
export { ConfigurationError, IdentityError, assertOrganizationPin, getIdentityFromRequest, parsePublicKeys, resolveVerifyOptions, verifyIdentity, verifyIdentityJwt, verifyPublicMarkerJwt, verifySystemJwt, type IdentityResult, type RequestIdentityOptions, type VerifiedIdentity, type VerifyOptions, } from "./identity.js";
|
|
19
24
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC"}
|
package/dist/internal/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./protocol.js";
|
|
|
2
2
|
export * from "./tools.js";
|
|
3
3
|
export * from "./capabilities.js";
|
|
4
4
|
export * from "./aiProviders.js";
|
|
5
|
+
export * from "./aiDefault.js";
|
|
5
6
|
export * from "./gatewaySettings.js";
|
|
6
7
|
export * from "./appSettings.js";
|
|
7
8
|
export * from "./email.js";
|
|
@@ -9,10 +10,14 @@ export * from "./members.js";
|
|
|
9
10
|
export * from "./organizationName.js";
|
|
10
11
|
export * from "./oauthClient.js";
|
|
11
12
|
export * from "./oauthScopes.js";
|
|
13
|
+
export * from "./oauthSpec.js";
|
|
14
|
+
export * from "./oauthPresets.js";
|
|
12
15
|
export * from "./providerApps.js";
|
|
13
16
|
export * from "./events.js";
|
|
17
|
+
export * from "./audit.js";
|
|
14
18
|
export * from "./providerSpec.js";
|
|
15
19
|
export * from "./providerRegistry.js";
|
|
16
20
|
export * from "./remoteMcp.js";
|
|
21
|
+
export * from "./signInProviders.js";
|
|
17
22
|
export * from "./devProviders.js";
|
|
18
|
-
export { ConfigurationError, IdentityError, getIdentityFromRequest, parsePublicKeys, resolveVerifyOptions, verifyIdentityJwt, verifyPublicMarkerJwt, verifySystemJwt, } from "./identity.js";
|
|
23
|
+
export { ConfigurationError, IdentityError, assertOrganizationPin, getIdentityFromRequest, parsePublicKeys, resolveVerifyOptions, verifyIdentity, verifyIdentityJwt, verifyPublicMarkerJwt, verifySystemJwt, } from "./identity.js";
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* gateway builds it, the SDK's `listMembers()` returns it, and its local-dev
|
|
5
5
|
* fallback answers in the same shape. Types only.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import type { OrgRole } from "./protocol.js";
|
|
8
|
+
/** A member's role in the organization: the identity token's {@link OrgRole}. */
|
|
9
|
+
export type OrganizationMemberRole = OrgRole;
|
|
9
10
|
/**
|
|
10
11
|
* One member of the organization who can open the app: not deactivated,
|
|
11
12
|
* and, for an organization's own app, granted it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"members.d.ts","sourceRoot":"","sources":["../../src/internal/members.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,
|
|
1
|
+
{"version":3,"file":"members.d.ts","sourceRoot":"","sources":["../../src/internal/members.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,iFAAiF;AACjF,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAE7C;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,sBAAsB,CAAC;CAC9B;AAED,2BAA2B;AAC3B,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B;AAED,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,SAAS,CAAC;IACtB,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,UAAU,EAAE,IAAI,CAAC;IACjB,8BAA8B;IAC9B,KAAK,EAAE,OAAO,CAAC;CAChB"}
|
|
@@ -15,8 +15,7 @@ export interface OAuthClientCredentials {
|
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* The client `settings` hold for `capability`, or null until every setting
|
|
18
|
-
* it needs is set: the id, the secret
|
|
19
|
-
* `hostSetting` that is an https origin when it is set at all.
|
|
18
|
+
* it needs is set: the id, and the secret unless it is a public client.
|
|
20
19
|
*/
|
|
21
20
|
export declare function oauthClientCredentials(capability: OAuthClientCapability, settings: CapabilitySettings): OAuthClientCredentials | null;
|
|
22
21
|
/** A token request: where it goes, its headers, its (buffered) body. */
|
|
@@ -32,26 +31,25 @@ export type InjectedTokenRequest = ({
|
|
|
32
31
|
problem: string;
|
|
33
32
|
};
|
|
34
33
|
/**
|
|
35
|
-
* `request` with `client` put where `rule` says (the form body
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* Token requests are form-encoded or JSON; anything else is refused.
|
|
34
|
+
* `request` with `client` put where `rule` says (the form body or HTTP
|
|
35
|
+
* Basic), and every client credential the app sent removed wherever it
|
|
36
|
+
* was: the `Authorization` header, and `client_id`/`client_secret` (in any
|
|
37
|
+
* case) in the query string and the body. The body is re-serialised from
|
|
38
|
+
* its parsed values, so a crafted body can't carry a second secret past
|
|
39
|
+
* the parser. Token requests are form-encoded; anything else is refused.
|
|
42
40
|
*/
|
|
43
41
|
export declare function injectClientCredentials(request: TokenRequest, rule: OAuthTokenEndpoint, client: OAuthClientCredentials): InjectedTokenRequest;
|
|
44
42
|
/**
|
|
45
43
|
* The grants the gateway completes: each ends in a user's own tokens. The
|
|
46
44
|
* client-credentials grant, and anything else a network serves on the same
|
|
47
45
|
* endpoint, would mint a token for the gateway's own application instead,
|
|
48
|
-
* which on
|
|
49
|
-
*
|
|
46
|
+
* which on many providers manages the application's settings, its
|
|
47
|
+
* webhooks and every tenant's tokens.
|
|
50
48
|
*/
|
|
51
49
|
export declare const USER_BOUND_GRANT_TYPES: ReadonlySet<string>;
|
|
52
50
|
/**
|
|
53
51
|
* A token request's `grant_type` as the app sent it, from its body or query
|
|
54
|
-
* string, or null when it names none (
|
|
52
|
+
* string, or null when it names none (Slack's code exchange). Never the
|
|
55
53
|
* request's other fields.
|
|
56
54
|
*/
|
|
57
55
|
export declare function requestedGrantType(request: TokenRequest): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauthClient.d.ts","sourceRoot":"","sources":["../../src/internal/oauthClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"oauthClient.d.ts","sourceRoot":"","sources":["../../src/internal/oauthClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAE3B,2FAA2F;AAC3F,eAAO,MAAM,sBAAsB,QAAY,CAAC;AAEhD,gEAAgE;AAChE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,qBAAqB,EACjC,QAAQ,EAAE,kBAAkB,GAC3B,sBAAsB,GAAG,IAAI,CAQ/B;AAMD,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,GAAG,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,MAAM,oBAAoB,GAC5B,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,YAAY,CAAC,GAC7B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAOnC;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,sBAAsB,GAC7B,oBAAoB,CAoDtB;AAUD;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAIrD,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAQvE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAInE"}
|
|
@@ -4,13 +4,12 @@
|
|
|
4
4
|
* app's token request, and the SDK's local-dev fallback, which puts the
|
|
5
5
|
* developer's own on it the same way.
|
|
6
6
|
*/
|
|
7
|
-
import { base64Utf8,
|
|
7
|
+
import { base64Utf8, } from "./capabilities.js";
|
|
8
8
|
/** The largest token request body the gateway reads: real ones are a few hundred bytes. */
|
|
9
9
|
export const OAUTH_TOKEN_BODY_LIMIT = 64 * 1024;
|
|
10
10
|
/**
|
|
11
11
|
* The client `settings` hold for `capability`, or null until every setting
|
|
12
|
-
* it needs is set: the id, the secret
|
|
13
|
-
* `hostSetting` that is an https origin when it is set at all.
|
|
12
|
+
* it needs is set: the id, and the secret unless it is a public client.
|
|
14
13
|
*/
|
|
15
14
|
export function oauthClientCredentials(capability, settings) {
|
|
16
15
|
const clientId = settingValue(settings[capability.secrets.clientId]);
|
|
@@ -20,72 +19,53 @@ export function oauthClientCredentials(capability, settings) {
|
|
|
20
19
|
: undefined;
|
|
21
20
|
if (!clientId || (secretName && !clientSecret))
|
|
22
21
|
return null;
|
|
23
|
-
if (capability.hostSetting && !oauthClientOrigin(capability, settings)) {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
22
|
return { clientId, ...(clientSecret ? { clientSecret } : {}) };
|
|
27
23
|
}
|
|
28
24
|
function settingValue(value) {
|
|
29
25
|
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
30
26
|
}
|
|
31
27
|
const FORM = "application/x-www-form-urlencoded";
|
|
32
|
-
const
|
|
28
|
+
const isCredential = (name) => ["client_id", "client_secret"].includes(name.toLowerCase());
|
|
33
29
|
/**
|
|
34
|
-
* `request` with `client` put where `rule` says (the form body
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* Token requests are form-encoded or JSON; anything else is refused.
|
|
30
|
+
* `request` with `client` put where `rule` says (the form body or HTTP
|
|
31
|
+
* Basic), and every client credential the app sent removed wherever it
|
|
32
|
+
* was: the `Authorization` header, and `client_id`/`client_secret` (in any
|
|
33
|
+
* case) in the query string and the body. The body is re-serialised from
|
|
34
|
+
* its parsed values, so a crafted body can't carry a second secret past
|
|
35
|
+
* the parser. Token requests are form-encoded; anything else is refused.
|
|
41
36
|
*/
|
|
42
37
|
export function injectClientCredentials(request, rule, client) {
|
|
43
|
-
const idName = rule.params?.clientId ?? "client_id";
|
|
44
|
-
const secretName = rule.params?.clientSecret ?? "client_secret";
|
|
45
|
-
const credentialNames = new Set(["client_id", "client_secret", idName, secretName].map((name) => name.toLowerCase()));
|
|
46
|
-
const isCredential = (name) => credentialNames.has(name.toLowerCase());
|
|
47
38
|
const fields = [
|
|
48
|
-
[
|
|
39
|
+
["client_id", client.clientId],
|
|
49
40
|
...(client.clientSecret
|
|
50
|
-
? [[
|
|
41
|
+
? [["client_secret", client.clientSecret]]
|
|
51
42
|
: []),
|
|
52
43
|
];
|
|
53
44
|
// The query keeps the app's other fields as they were sent.
|
|
54
45
|
const url = new URL(request.url);
|
|
55
|
-
|
|
46
|
+
url.search = url.search
|
|
56
47
|
.slice(1)
|
|
57
48
|
.split("&")
|
|
58
49
|
.filter((pair) => {
|
|
59
50
|
const [name] = new URLSearchParams(pair).keys();
|
|
60
51
|
return pair !== "" && !(name !== undefined && isCredential(name));
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
query.push(new URLSearchParams(fields).toString());
|
|
64
|
-
}
|
|
65
|
-
url.search = query.join("&");
|
|
52
|
+
})
|
|
53
|
+
.join("&");
|
|
66
54
|
const headers = new Headers(request.headers);
|
|
67
55
|
headers.delete("authorization");
|
|
68
56
|
headers.delete("content-length");
|
|
69
57
|
if (rule.inject === "basic") {
|
|
70
58
|
headers.set("authorization", `Basic ${base64Utf8(`${client.clientId}:${client.clientSecret ?? ""}`)}`);
|
|
71
59
|
}
|
|
72
|
-
const type = mediaType(headers.get("content-type"));
|
|
73
60
|
let body = request.body;
|
|
74
61
|
if (body === null || body === "") {
|
|
75
|
-
// Nothing the app sent; the form
|
|
62
|
+
// Nothing the app sent; the form rule makes the body.
|
|
76
63
|
if (rule.inject === "form") {
|
|
77
64
|
headers.set("content-type", FORM);
|
|
78
65
|
body = new URLSearchParams(fields).toString();
|
|
79
66
|
}
|
|
80
|
-
else if (rule.inject === "json") {
|
|
81
|
-
headers.set("content-type", JSON_TYPE);
|
|
82
|
-
body = JSON.stringify(Object.fromEntries(fields));
|
|
83
|
-
}
|
|
84
67
|
}
|
|
85
|
-
else if (type === FORM) {
|
|
86
|
-
if (rule.inject === "json") {
|
|
87
|
-
return { ok: false, problem: "This token endpoint takes a JSON body." };
|
|
88
|
-
}
|
|
68
|
+
else if (mediaType(headers.get("content-type")) === FORM) {
|
|
89
69
|
const params = new URLSearchParams(body);
|
|
90
70
|
for (const name of new Set([...params.keys()].filter(isCredential))) {
|
|
91
71
|
params.delete(name);
|
|
@@ -96,31 +76,10 @@ export function injectClientCredentials(request, rule, client) {
|
|
|
96
76
|
}
|
|
97
77
|
body = params.toString();
|
|
98
78
|
}
|
|
99
|
-
else if (type === JSON_TYPE) {
|
|
100
|
-
if (rule.inject === "form") {
|
|
101
|
-
return {
|
|
102
|
-
ok: false,
|
|
103
|
-
problem: `This token endpoint takes a form-encoded body (${FORM}).`,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
const parsed = jsonObject(body);
|
|
107
|
-
if (!parsed) {
|
|
108
|
-
return { ok: false, problem: "The body is not a JSON object." };
|
|
109
|
-
}
|
|
110
|
-
for (const name of Object.keys(parsed)) {
|
|
111
|
-
if (isCredential(name))
|
|
112
|
-
delete parsed[name];
|
|
113
|
-
}
|
|
114
|
-
if (rule.inject === "json") {
|
|
115
|
-
for (const [name, value] of fields)
|
|
116
|
-
parsed[name] = value;
|
|
117
|
-
}
|
|
118
|
-
body = JSON.stringify(parsed);
|
|
119
|
-
}
|
|
120
79
|
else {
|
|
121
80
|
return {
|
|
122
81
|
ok: false,
|
|
123
|
-
problem: `A token request's body is form-encoded (${FORM})
|
|
82
|
+
problem: `A token request's body is form-encoded (${FORM}).`,
|
|
124
83
|
};
|
|
125
84
|
}
|
|
126
85
|
return { ok: true, url, headers, body };
|
|
@@ -130,29 +89,23 @@ const GRANT_TYPES = new Set([
|
|
|
130
89
|
"authorization_code",
|
|
131
90
|
"refresh_token",
|
|
132
91
|
"client_credentials",
|
|
133
|
-
"fb_exchange_token",
|
|
134
|
-
"ig_exchange_token",
|
|
135
|
-
"th_exchange_token",
|
|
136
92
|
"urn:ietf:params:oauth:grant-type:token-exchange",
|
|
137
93
|
]);
|
|
138
94
|
/**
|
|
139
95
|
* The grants the gateway completes: each ends in a user's own tokens. The
|
|
140
96
|
* client-credentials grant, and anything else a network serves on the same
|
|
141
97
|
* endpoint, would mint a token for the gateway's own application instead,
|
|
142
|
-
* which on
|
|
143
|
-
*
|
|
98
|
+
* which on many providers manages the application's settings, its
|
|
99
|
+
* webhooks and every tenant's tokens.
|
|
144
100
|
*/
|
|
145
101
|
export const USER_BOUND_GRANT_TYPES = new Set([
|
|
146
102
|
"authorization_code",
|
|
147
103
|
"refresh_token",
|
|
148
|
-
"fb_exchange_token",
|
|
149
|
-
"ig_exchange_token",
|
|
150
|
-
"th_exchange_token",
|
|
151
104
|
"urn:ietf:params:oauth:grant-type:token-exchange",
|
|
152
105
|
]);
|
|
153
106
|
/**
|
|
154
107
|
* A token request's `grant_type` as the app sent it, from its body or query
|
|
155
|
-
* string, or null when it names none (
|
|
108
|
+
* string, or null when it names none (Slack's code exchange). Never the
|
|
156
109
|
* request's other fields.
|
|
157
110
|
*/
|
|
158
111
|
export function requestedGrantType(request) {
|
|
@@ -161,9 +114,6 @@ export function requestedGrantType(request) {
|
|
|
161
114
|
if (request.body && type === FORM) {
|
|
162
115
|
value = new URLSearchParams(request.body).get("grant_type");
|
|
163
116
|
}
|
|
164
|
-
else if (request.body && type === JSON_TYPE) {
|
|
165
|
-
value = jsonObject(request.body)?.["grant_type"] ?? null;
|
|
166
|
-
}
|
|
167
117
|
value ??= request.url.searchParams.get("grant_type");
|
|
168
118
|
return typeof value === "string" && value ? value : null;
|
|
169
119
|
}
|
|
@@ -181,14 +131,3 @@ export function tokenGrantType(request) {
|
|
|
181
131
|
function mediaType(contentType) {
|
|
182
132
|
return (contentType ?? "").split(";")[0].trim().toLowerCase();
|
|
183
133
|
}
|
|
184
|
-
function jsonObject(text) {
|
|
185
|
-
try {
|
|
186
|
-
const value = JSON.parse(text);
|
|
187
|
-
return value && typeof value === "object" && !Array.isArray(value)
|
|
188
|
-
? value
|
|
189
|
-
: null;
|
|
190
|
-
}
|
|
191
|
-
catch {
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
}
|