@stigmer/server 3.24.0 → 3.25.0
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/dist/authorization/authorizer.d.ts +10 -4
- package/dist/authorization/authorizer.d.ts.map +1 -1
- package/dist/authorization/authorizer.js +11 -4
- package/dist/authorization/authorizer.js.map +1 -1
- package/dist/authorization/model/index.d.ts +4 -4
- package/dist/authorization/model/index.d.ts.map +1 -1
- package/dist/authorization/model/index.js +2 -0
- package/dist/authorization/model/index.js.map +1 -1
- package/dist/authorization/model/oauth_app.d.ts.map +1 -1
- package/dist/authorization/model/oauth_app.js +3 -2
- package/dist/authorization/model/oauth_app.js.map +1 -1
- package/dist/authorization/model/platform_client.d.ts +2 -0
- package/dist/authorization/model/platform_client.d.ts.map +1 -0
- package/dist/authorization/model/platform_client.js +31 -0
- package/dist/authorization/model/platform_client.js.map +1 -0
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +88 -5
- package/dist/boot/compose.js.map +1 -1
- package/dist/boot/route-shadowing.d.ts +25 -0
- package/dist/boot/route-shadowing.d.ts.map +1 -0
- package/dist/boot/route-shadowing.js +17 -0
- package/dist/boot/route-shadowing.js.map +1 -0
- package/dist/domain/iampolicy/membership.d.ts +6 -1
- package/dist/domain/iampolicy/membership.d.ts.map +1 -1
- package/dist/domain/iampolicy/membership.js +8 -2
- package/dist/domain/iampolicy/membership.js.map +1 -1
- package/dist/domain/identityaccount/constants.d.ts +13 -0
- package/dist/domain/identityaccount/constants.d.ts.map +1 -1
- package/dist/domain/identityaccount/constants.js +17 -0
- package/dist/domain/identityaccount/constants.js.map +1 -1
- package/dist/domain/identityaccount/controller.d.ts +3 -1
- package/dist/domain/identityaccount/controller.d.ts.map +1 -1
- package/dist/domain/identityaccount/controller.js +15 -6
- package/dist/domain/identityaccount/controller.js.map +1 -1
- package/dist/domain/identityaccount/operator.d.ts.map +1 -1
- package/dist/domain/identityaccount/operator.js +1 -0
- package/dist/domain/identityaccount/operator.js.map +1 -1
- package/dist/domain/identityaccount/provisioning.d.ts +18 -0
- package/dist/domain/identityaccount/provisioning.d.ts.map +1 -1
- package/dist/domain/identityaccount/provisioning.js +1 -0
- package/dist/domain/identityaccount/provisioning.js.map +1 -1
- package/dist/domain/identityaccount/resource-store.js +9 -5
- package/dist/domain/identityaccount/resource-store.js.map +1 -1
- package/dist/domain/identityaccount/steps.d.ts +11 -2
- package/dist/domain/identityaccount/steps.d.ts.map +1 -1
- package/dist/domain/identityaccount/steps.js +42 -4
- package/dist/domain/identityaccount/steps.js.map +1 -1
- package/dist/domain/identityaccount/store-contract.d.ts.map +1 -1
- package/dist/domain/identityaccount/store-contract.js +33 -0
- package/dist/domain/identityaccount/store-contract.js.map +1 -1
- package/dist/domain/identityaccount/store.d.ts +7 -5
- package/dist/domain/identityaccount/store.d.ts.map +1 -1
- package/dist/domain/identityaccount/store.js.map +1 -1
- package/dist/domain/platform/controller.d.ts +10 -0
- package/dist/domain/platform/controller.d.ts.map +1 -1
- package/dist/domain/platform/controller.js +2 -1
- package/dist/domain/platform/controller.js.map +1 -1
- package/dist/domain/platformclient/constants.d.ts +60 -0
- package/dist/domain/platformclient/constants.d.ts.map +1 -0
- package/dist/domain/platformclient/constants.js +78 -0
- package/dist/domain/platformclient/constants.js.map +1 -0
- package/dist/domain/platformclient/controller.d.ts +59 -0
- package/dist/domain/platformclient/controller.d.ts.map +1 -0
- package/dist/domain/platformclient/controller.js +191 -0
- package/dist/domain/platformclient/controller.js.map +1 -0
- package/dist/domain/platformclient/credentials.d.ts +13 -0
- package/dist/domain/platformclient/credentials.d.ts.map +1 -0
- package/dist/domain/platformclient/credentials.js +56 -0
- package/dist/domain/platformclient/credentials.js.map +1 -0
- package/dist/domain/platformclient/mint.d.ts +23 -0
- package/dist/domain/platformclient/mint.d.ts.map +1 -0
- package/dist/domain/platformclient/mint.js +254 -0
- package/dist/domain/platformclient/mint.js.map +1 -0
- package/dist/domain/platformclient/origin-guard.d.ts +9 -0
- package/dist/domain/platformclient/origin-guard.d.ts.map +1 -0
- package/dist/domain/platformclient/origin-guard.js +81 -0
- package/dist/domain/platformclient/origin-guard.js.map +1 -0
- package/dist/domain/platformclient/resource-store.d.ts +4 -0
- package/dist/domain/platformclient/resource-store.d.ts.map +1 -0
- package/dist/domain/platformclient/resource-store.js +117 -0
- package/dist/domain/platformclient/resource-store.js.map +1 -0
- package/dist/domain/platformclient/steps.d.ts +51 -0
- package/dist/domain/platformclient/steps.d.ts.map +1 -0
- package/dist/domain/platformclient/steps.js +339 -0
- package/dist/domain/platformclient/steps.js.map +1 -0
- package/dist/domain/platformclient/store-contract.d.ts +8 -0
- package/dist/domain/platformclient/store-contract.d.ts.map +1 -0
- package/dist/domain/platformclient/store-contract.js +208 -0
- package/dist/domain/platformclient/store-contract.js.map +1 -0
- package/dist/domain/platformclient/store.d.ts +58 -0
- package/dist/domain/platformclient/store.d.ts.map +1 -0
- package/dist/domain/platformclient/store.js +13 -0
- package/dist/domain/platformclient/store.js.map +1 -0
- package/dist/domain/platformclient/system-managed.d.ts +18 -0
- package/dist/domain/platformclient/system-managed.d.ts.map +1 -0
- package/dist/domain/platformclient/system-managed.js +80 -0
- package/dist/domain/platformclient/system-managed.js.map +1 -0
- package/dist/domain/platformclient/token-controller.d.ts +11 -0
- package/dist/domain/platformclient/token-controller.d.ts.map +1 -0
- package/dist/domain/platformclient/token-controller.js +32 -0
- package/dist/domain/platformclient/token-controller.js.map +1 -0
- package/dist/domain/platformclient/verifier.d.ts +10 -0
- package/dist/domain/platformclient/verifier.d.ts.map +1 -0
- package/dist/domain/platformclient/verifier.js +76 -0
- package/dist/domain/platformclient/verifier.js.map +1 -0
- package/dist/encryption/key-manager.d.ts +20 -3
- package/dist/encryption/key-manager.d.ts.map +1 -1
- package/dist/encryption/key-manager.js +64 -42
- package/dist/encryption/key-manager.js.map +1 -1
- package/dist/extensions/caller-guards.d.ts +8 -3
- package/dist/extensions/caller-guards.d.ts.map +1 -1
- package/dist/extensions/drivers.d.ts +37 -0
- package/dist/extensions/drivers.d.ts.map +1 -1
- package/dist/extensions/guest-token-minting.d.ts +26 -0
- package/dist/extensions/guest-token-minting.d.ts.map +1 -0
- package/dist/extensions/guest-token-minting.js +2 -0
- package/dist/extensions/guest-token-minting.js.map +1 -0
- package/dist/extensions/identity.d.ts +6 -4
- package/dist/extensions/identity.d.ts.map +1 -1
- package/dist/extensions/identity.js.map +1 -1
- package/dist/extensions/registry.d.ts +30 -1
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/extensions/registry.js +34 -1
- package/dist/extensions/registry.js.map +1 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/interceptors/auth.d.ts +14 -0
- package/dist/pipeline/interceptors/auth.d.ts.map +1 -1
- package/dist/pipeline/interceptors/auth.js +24 -0
- package/dist/pipeline/interceptors/auth.js.map +1 -1
- package/dist/pipeline/steps/build-update-state.d.ts +11 -1
- package/dist/pipeline/steps/build-update-state.d.ts.map +1 -1
- package/dist/pipeline/steps/build-update-state.js +5 -2
- package/dist/pipeline/steps/build-update-state.js.map +1 -1
- package/dist/platformtoken/envelope.d.ts +100 -0
- package/dist/platformtoken/envelope.d.ts.map +1 -0
- package/dist/platformtoken/envelope.js +184 -0
- package/dist/platformtoken/envelope.js.map +1 -0
- package/dist/platformtoken/key-ring.d.ts +85 -0
- package/dist/platformtoken/key-ring.d.ts.map +1 -0
- package/dist/platformtoken/key-ring.js +164 -0
- package/dist/platformtoken/key-ring.js.map +1 -0
- package/package.json +6 -6
- package/src/authorization/README.md +1 -1
- package/src/authorization/__tests__/authorizer.test.ts +6 -2
- package/src/authorization/__tests__/wire-permissions.test.ts +1 -0
- package/src/authorization/authorizer.ts +11 -4
- package/src/authorization/model/__tests__/registry.test.ts +8 -1
- package/src/authorization/model/index.ts +6 -4
- package/src/authorization/model/oauth_app.ts +3 -2
- package/src/authorization/model/platform_client.ts +43 -0
- package/src/boot/__tests__/auth-enabled-composition.test.ts +2 -1
- package/src/boot/__tests__/route-shadowing.test.ts +67 -0
- package/src/boot/compose.ts +90 -5
- package/src/boot/route-shadowing.ts +47 -0
- package/src/domain/iampolicy/__tests__/membership.test.ts +7 -0
- package/src/domain/iampolicy/membership.ts +8 -2
- package/src/domain/identityaccount/__tests__/platform-client-accounts.test.ts +124 -0
- package/src/domain/identityaccount/__tests__/resource-store.test.ts +1 -0
- package/src/domain/identityaccount/constants.ts +20 -0
- package/src/domain/identityaccount/controller.ts +16 -4
- package/src/domain/identityaccount/operator.ts +1 -0
- package/src/domain/identityaccount/provisioning.ts +17 -0
- package/src/domain/identityaccount/resource-store.ts +9 -5
- package/src/domain/identityaccount/steps.ts +58 -3
- package/src/domain/identityaccount/store-contract.ts +51 -0
- package/src/domain/identityaccount/store.ts +7 -5
- package/src/domain/platform/__tests__/platform.test.ts +7 -1
- package/src/domain/platform/controller.ts +12 -1
- package/src/domain/platformclient/__tests__/controller.test.ts +397 -0
- package/src/domain/platformclient/__tests__/credentials.test.ts +46 -0
- package/src/domain/platformclient/__tests__/mint.test.ts +415 -0
- package/src/domain/platformclient/__tests__/resource-store.test.ts +140 -0
- package/src/domain/platformclient/__tests__/system-managed.test.ts +101 -0
- package/src/domain/platformclient/__tests__/verifier-and-guard.test.ts +207 -0
- package/src/domain/platformclient/constants.ts +120 -0
- package/src/domain/platformclient/controller.ts +449 -0
- package/src/domain/platformclient/credentials.ts +68 -0
- package/src/domain/platformclient/mint.ts +412 -0
- package/src/domain/platformclient/origin-guard.ts +117 -0
- package/src/domain/platformclient/resource-store.ts +150 -0
- package/src/domain/platformclient/steps.ts +472 -0
- package/src/domain/platformclient/store-contract.ts +318 -0
- package/src/domain/platformclient/store.ts +63 -0
- package/src/domain/platformclient/system-managed.ts +115 -0
- package/src/domain/platformclient/token-controller.ts +49 -0
- package/src/domain/platformclient/verifier.ts +106 -0
- package/src/encryption/key-manager.ts +87 -44
- package/src/extensions/__tests__/extension-composition.test.ts +3 -2
- package/src/extensions/__tests__/platform-client-composed.test.ts +288 -0
- package/src/extensions/__tests__/registry.test.ts +4 -1
- package/src/extensions/__tests__/tier-truthfulness.test.ts +8 -0
- package/src/extensions/caller-guards.ts +8 -3
- package/src/extensions/drivers.ts +37 -0
- package/src/extensions/guest-token-minting.ts +32 -0
- package/src/extensions/identity.ts +6 -4
- package/src/extensions/registry.ts +77 -3
- package/src/index.ts +55 -0
- package/src/pipeline/interceptors/auth.ts +27 -0
- package/src/pipeline/steps/__tests__/references.test.ts +2 -0
- package/src/pipeline/steps/build-update-state.ts +5 -2
- package/src/platformtoken/__tests__/envelope.test.ts +277 -0
- package/src/platformtoken/__tests__/key-ring.test.ts +205 -0
- package/src/platformtoken/envelope.ts +276 -0
- package/src/platformtoken/key-ring.ts +266 -0
- package/src/runnerauth/__tests__/runner-subject-composed.test.ts +9 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.js","sourceRoot":"","sources":["../../../src/domain/platformclient/controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const CLIENT_ID_PREFIX = "stgm_cid_";
|
|
2
|
+
export declare const CLIENT_SECRET_PREFIX = "stgm_cs_";
|
|
3
|
+
/** Characters of the secret kept for display. */
|
|
4
|
+
export declare const SECRET_FINGERPRINT_LENGTH = 6;
|
|
5
|
+
export declare function generateClientId(): string;
|
|
6
|
+
export declare function generateClientSecret(): string;
|
|
7
|
+
/** SHA-256 over the whole prefixed secret, base64url — the stored form. */
|
|
8
|
+
export declare function hashClientSecret(secret: string): string;
|
|
9
|
+
/** The secret's last six characters (the whole secret when shorter). */
|
|
10
|
+
export declare function secretFingerprint(secret: string): string;
|
|
11
|
+
/** Whether `secret` hashes to `storedHash`, compared in constant time. */
|
|
12
|
+
export declare function secretMatchesHash(secret: string, storedHash: string): boolean;
|
|
13
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../../src/domain/platformclient/credentials.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAC5C,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAQ/C,iDAAiD;AACjD,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAK7C;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAS7E"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PlatformClient credential material — byte-compatible with every client
|
|
3
|
+
* Stigmer Cloud has issued since the Java service, because the rows (and
|
|
4
|
+
* the secrets integrators hold) move under this code unchanged:
|
|
5
|
+
*
|
|
6
|
+
* - client_id: "stgm_cid_" + 32 random bytes, base64url (43 characters).
|
|
7
|
+
* Public by design — safe in logs and client-side code — so its
|
|
8
|
+
* existence is no secret and the mint may answer an unknown id and a
|
|
9
|
+
* wrong secret with the same copy at different speeds.
|
|
10
|
+
* - client_secret: "stgm_cs_" + 48 random bytes, base64url (64
|
|
11
|
+
* characters): 384 bits, returned once and never stored.
|
|
12
|
+
* - the stored hash: SHA-256 over the whole prefixed secret, base64url
|
|
13
|
+
* (43 characters). A slow KDF defends low-entropy passwords, not
|
|
14
|
+
* 384-bit random tokens — ApiKey's precedent (domain/apikey/keymaterial.ts).
|
|
15
|
+
* - the fingerprint: the secret's last six characters, for display.
|
|
16
|
+
*
|
|
17
|
+
* The comparison hashes the presented secret and compares the two hashes in
|
|
18
|
+
* constant time, so neither the secret nor the stored hash leaks through
|
|
19
|
+
* timing.
|
|
20
|
+
*/
|
|
21
|
+
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
22
|
+
export const CLIENT_ID_PREFIX = "stgm_cid_";
|
|
23
|
+
export const CLIENT_SECRET_PREFIX = "stgm_cs_";
|
|
24
|
+
/** Random bytes behind a client_id. */
|
|
25
|
+
const CLIENT_ID_BYTES = 32;
|
|
26
|
+
/** Random bytes behind a client_secret: 384 bits. */
|
|
27
|
+
const CLIENT_SECRET_BYTES = 48;
|
|
28
|
+
/** Characters of the secret kept for display. */
|
|
29
|
+
export const SECRET_FINGERPRINT_LENGTH = 6;
|
|
30
|
+
export function generateClientId() {
|
|
31
|
+
return CLIENT_ID_PREFIX + randomBytes(CLIENT_ID_BYTES).toString("base64url");
|
|
32
|
+
}
|
|
33
|
+
export function generateClientSecret() {
|
|
34
|
+
return (CLIENT_SECRET_PREFIX +
|
|
35
|
+
randomBytes(CLIENT_SECRET_BYTES).toString("base64url"));
|
|
36
|
+
}
|
|
37
|
+
/** SHA-256 over the whole prefixed secret, base64url — the stored form. */
|
|
38
|
+
export function hashClientSecret(secret) {
|
|
39
|
+
return createHash("sha256").update(secret, "utf8").digest("base64url");
|
|
40
|
+
}
|
|
41
|
+
/** The secret's last six characters (the whole secret when shorter). */
|
|
42
|
+
export function secretFingerprint(secret) {
|
|
43
|
+
return secret.length <= SECRET_FINGERPRINT_LENGTH
|
|
44
|
+
? secret
|
|
45
|
+
: secret.slice(-SECRET_FINGERPRINT_LENGTH);
|
|
46
|
+
}
|
|
47
|
+
/** Whether `secret` hashes to `storedHash`, compared in constant time. */
|
|
48
|
+
export function secretMatchesHash(secret, storedHash) {
|
|
49
|
+
if (storedHash === "") {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const presented = Buffer.from(hashClientSecret(secret), "utf8");
|
|
53
|
+
const stored = Buffer.from(storedHash, "utf8");
|
|
54
|
+
return (presented.length === stored.length && timingSafeEqual(presented, stored));
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../src/domain/platformclient/credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAC5C,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE/C,uCAAuC;AACvC,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B,qDAAqD;AACrD,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,iDAAiD;AACjD,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAE3C,MAAM,UAAU,gBAAgB;IAC9B,OAAO,gBAAgB,GAAG,WAAW,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,CACL,oBAAoB;QACpB,WAAW,CAAC,mBAAmB,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CACvD,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACzE,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,MAAM,CAAC,MAAM,IAAI,yBAAyB;QAC/C,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,yBAAyB,CAAC,CAAC;AAC/C,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,UAAkB;IAClE,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC/C,OAAO,CACL,SAAS,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,IAAI,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,CACzE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { MintUserTokenRequest, MintUserTokenResponse } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/token_pb";
|
|
2
|
+
import type { Logger } from "../../boot/logger.js";
|
|
3
|
+
import { type PlatformTokenKeyRing } from "../../platformtoken/key-ring.js";
|
|
4
|
+
import type { IamPolicyGrantPath } from "../iampolicy/grant-path.js";
|
|
5
|
+
import type { CreateAccount } from "../identityaccount/provisioning.js";
|
|
6
|
+
import type { IdentityAccountStore } from "../identityaccount/store.js";
|
|
7
|
+
import type { PlatformClientStore } from "./store.js";
|
|
8
|
+
export interface PlatformClientMintDeps {
|
|
9
|
+
readonly clients: PlatformClientStore;
|
|
10
|
+
/** The any-mode subject lookup: an existing end user is found whatever wrote it. */
|
|
11
|
+
readonly accounts: Pick<IdentityAccountStore, "findByIdpId">;
|
|
12
|
+
/** The identity-account domain's one create path (identityaccount/controller.ts). */
|
|
13
|
+
readonly createAccount: CreateAccount;
|
|
14
|
+
readonly grantPath: Pick<IamPolicyGrantPath, "grant">;
|
|
15
|
+
/** The composed ring; undefined when the server trusts every request. */
|
|
16
|
+
readonly keys: PlatformTokenKeyRing | undefined;
|
|
17
|
+
readonly logger: Logger;
|
|
18
|
+
readonly now: () => Date;
|
|
19
|
+
}
|
|
20
|
+
export declare function mintUserToken(deps: PlatformClientMintDeps, request: MintUserTokenRequest): Promise<MintUserTokenResponse>;
|
|
21
|
+
/** `stgm_pc|<org>|<user_id>`, each part non-blank and free of the separator. */
|
|
22
|
+
export declare function platformClientSubject(org: string, externalUserId: string): string;
|
|
23
|
+
//# sourceMappingURL=mint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mint.d.ts","sourceRoot":"","sources":["../../../src/domain/platformclient/mint.ts"],"names":[],"mappings":"AAwDA,OAAO,KAAK,EACV,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,2DAA2D,CAAC;AAInE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAKnD,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAMrE,OAAO,KAAK,EACV,aAAa,EAEd,MAAM,oCAAoC,CAAC;AAE5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAiBxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAQtD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,oBAAoB,EAAE,aAAa,CAAC,CAAC;IAC7D,qFAAqF;IACrF,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;IACtD,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,IAAI,CAAC;CAC1B;AASD,wBAAsB,aAAa,CACjC,IAAI,EAAE,sBAAsB,EAC5B,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,CAmDhC;AA8LD,gFAAgF;AAChF,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,MAAM,GACrB,MAAM,CAIR"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PlatformClient mint: `mintUserToken`, the public RPC a platform's
|
|
3
|
+
* backend calls with its client_id + client_secret and one of its users,
|
|
4
|
+
* answered with a short-lived Stigmer user token for that user.
|
|
5
|
+
*
|
|
6
|
+
* The contract is the cloud's, refusal for refusal and in the same order
|
|
7
|
+
* (constants.ts carries the copy): the credentials, then the secret's
|
|
8
|
+
* expiry (unset means never), then the `org_id` confirmation (a token is
|
|
9
|
+
* always scoped to the client's owning organization), then the user.
|
|
10
|
+
*
|
|
11
|
+
* The user is keyed `stgm_pc|<org>|<user_id>`, so every client of one
|
|
12
|
+
* organization resolves one user to one account, and that account's id is
|
|
13
|
+
* derived from the subject (identityaccount/constants.ts accountIdFor). An
|
|
14
|
+
* account that exists is used as it is — its roles and profile stay what
|
|
15
|
+
* they are, whatever the client's settings say now — and must have been
|
|
16
|
+
* provisioned by a platform client: the subject namespace is reserved in
|
|
17
|
+
* both directions. An account that does not exist is provisioned when the
|
|
18
|
+
* client allows it, in this order:
|
|
19
|
+
*
|
|
20
|
+
* 1. The account's input is built and validated, so nothing below runs
|
|
21
|
+
* for a user the create chain would refuse.
|
|
22
|
+
* 2. When the client auto-grants, the role (viewer by default; never
|
|
23
|
+
* owner) is granted on the owning organization to the DERIVED account
|
|
24
|
+
* id, before the account row exists. The grant path is idempotent.
|
|
25
|
+
* 3. The account is created through the identity-account domain's one
|
|
26
|
+
* create path, in `platform_client` mode. A concurrent first mint that
|
|
27
|
+
* won the race is read back.
|
|
28
|
+
*
|
|
29
|
+
* Granting first is what makes every failure retry-safe with nothing to
|
|
30
|
+
* undo: a failed grant has written nothing; a failed create leaves one
|
|
31
|
+
* policy row naming an account that does not exist yet, which the next
|
|
32
|
+
* mint for that user completes. Creating first would need a rollback, and
|
|
33
|
+
* a rollback that fails leaves an account that can never receive its role
|
|
34
|
+
* (the existing-account arm never grants).
|
|
35
|
+
*
|
|
36
|
+
* Who acts: the request is public and tokenless, so the chain stamped the
|
|
37
|
+
* trusted-local operator on it — this module never reads that caller. The
|
|
38
|
+
* account and the policy are written as the CLIENT (`serverActingFor`, an
|
|
39
|
+
* `internal` caller naming the client's id), so the audit says which
|
|
40
|
+
* platform client brought the user in. End users are not people on the
|
|
41
|
+
* install: the membership rules never run for them (the create path is
|
|
42
|
+
* called directly, and identity-account provisioning's hook is not), and
|
|
43
|
+
* the boot reconciliation skips their mode (iampolicy/membership.ts).
|
|
44
|
+
*
|
|
45
|
+
* The email and name in the token and on the account are the platform's
|
|
46
|
+
* assertion; nothing on the server derives authority from either.
|
|
47
|
+
*/
|
|
48
|
+
import { Code, ConnectError } from "@connectrpc/connect";
|
|
49
|
+
import { create } from "@bufbuild/protobuf";
|
|
50
|
+
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
51
|
+
import { IdentityAccountSchema } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
|
|
52
|
+
import { IdentityAccountProvisioningMode } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/enum_pb";
|
|
53
|
+
import { IdentityAccountSpecSchema } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/spec_pb";
|
|
54
|
+
import { MintUserTokenResponseSchema } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/token_pb";
|
|
55
|
+
import { IamRole } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
|
|
56
|
+
import { internalError } from "../../pipeline/errors.js";
|
|
57
|
+
import { serverActingFor } from "../../pipeline/interceptors/auth.js";
|
|
58
|
+
import { validator } from "../../pipeline/steps/validation.js";
|
|
59
|
+
import { canSign, } from "../../platformtoken/key-ring.js";
|
|
60
|
+
import { signPlatformToken } from "../../platformtoken/envelope.js";
|
|
61
|
+
import { organizationRole } from "../iampolicy/specs.js";
|
|
62
|
+
import { PLATFORM_CLIENT_SUBJECT_PREFIX, accountIdFor, } from "../identityaccount/constants.js";
|
|
63
|
+
import { resolveCreateRace } from "../identityaccount/provisioning.js";
|
|
64
|
+
import { BEARER_TOKEN_TYPE, EXPIRED_CLIENT_SECRET_MESSAGE, INVALID_CLIENT_CREDENTIALS_MESSAGE, MINTING_DISABLED_MESSAGE, MINTING_REQUIRES_AUTHENTICATION_MESSAGE, OWNER_AUTO_GRANT_MESSAGE, PROVISIONING_FAILED_MESSAGE, USER_TOKEN_CLAIMS, blankSubjectPartMessage, foreignAccountMessage, noAccountMessage, organizationMismatchMessage, subjectSeparatorMessage, } from "./constants.js";
|
|
65
|
+
import { secretMatchesHash } from "./credentials.js";
|
|
66
|
+
/** The separator of the composite subject; neither part may contain it. */
|
|
67
|
+
const SUBJECT_SEPARATOR = "|";
|
|
68
|
+
/** The role an auto-grant gives when the client leaves it unspecified (the proto's default). */
|
|
69
|
+
const DEFAULT_AUTO_GRANT_ROLE = IamRole.viewer;
|
|
70
|
+
export async function mintUserToken(deps, request) {
|
|
71
|
+
const keys = deps.keys;
|
|
72
|
+
if (keys === undefined) {
|
|
73
|
+
throw new ConnectError(MINTING_REQUIRES_AUTHENTICATION_MESSAGE, Code.FailedPrecondition);
|
|
74
|
+
}
|
|
75
|
+
if (!canSign(keys)) {
|
|
76
|
+
throw new ConnectError(MINTING_DISABLED_MESSAGE, Code.FailedPrecondition);
|
|
77
|
+
}
|
|
78
|
+
const client = await authenticateClient(deps, request);
|
|
79
|
+
const owningOrg = client.metadata?.org ?? "";
|
|
80
|
+
// A confirmation, never a selector: a token is scoped to the owning org.
|
|
81
|
+
if (request.orgId !== "" && request.orgId !== owningOrg) {
|
|
82
|
+
throw new ConnectError(organizationMismatchMessage(owningOrg), Code.InvalidArgument);
|
|
83
|
+
}
|
|
84
|
+
const user = {
|
|
85
|
+
externalUserId: request.userId,
|
|
86
|
+
email: request.userEmail,
|
|
87
|
+
name: request.userName,
|
|
88
|
+
};
|
|
89
|
+
const accountId = await resolveOrProvisionAccount(deps, client, owningOrg, user);
|
|
90
|
+
const signed = signPlatformToken(keys, {
|
|
91
|
+
[USER_TOKEN_CLAIMS.subject]: accountId,
|
|
92
|
+
[USER_TOKEN_CLAIMS.externalUserId]: user.externalUserId,
|
|
93
|
+
[USER_TOKEN_CLAIMS.email]: user.email,
|
|
94
|
+
[USER_TOKEN_CLAIMS.name]: user.name,
|
|
95
|
+
[USER_TOKEN_CLAIMS.org]: owningOrg,
|
|
96
|
+
[USER_TOKEN_CLAIMS.platformClientId]: client.metadata?.id ?? "",
|
|
97
|
+
}, { now: deps.now() });
|
|
98
|
+
return create(MintUserTokenResponseSchema, {
|
|
99
|
+
accessToken: signed.token,
|
|
100
|
+
tokenType: BEARER_TOKEN_TYPE,
|
|
101
|
+
expiresIn: keys.ttlSeconds,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The client the credentials name, or UNAUTHENTICATED with one copy for an
|
|
106
|
+
* unknown client_id and a wrong secret alike; then the secret's expiry.
|
|
107
|
+
*/
|
|
108
|
+
async function authenticateClient(deps, request) {
|
|
109
|
+
let client;
|
|
110
|
+
try {
|
|
111
|
+
client = await deps.clients.findByClientId(request.clientId);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
throw internalError(error, "failed to authenticate platform client");
|
|
115
|
+
}
|
|
116
|
+
if (client === undefined ||
|
|
117
|
+
!secretMatchesHash(request.clientSecret, client.spec?.clientSecretHash ?? "")) {
|
|
118
|
+
throw new ConnectError(INVALID_CLIENT_CREDENTIALS_MESSAGE, Code.Unauthenticated);
|
|
119
|
+
}
|
|
120
|
+
const spec = client.spec;
|
|
121
|
+
if (spec?.neverExpires !== true &&
|
|
122
|
+
spec?.expiresAt !== undefined &&
|
|
123
|
+
deps.now().getTime() > timestampDate(spec.expiresAt).getTime()) {
|
|
124
|
+
throw new ConnectError(EXPIRED_CLIENT_SECRET_MESSAGE, Code.FailedPrecondition);
|
|
125
|
+
}
|
|
126
|
+
return client;
|
|
127
|
+
}
|
|
128
|
+
/** The account id for the user: the existing platform-client account, or one provisioned now. */
|
|
129
|
+
async function resolveOrProvisionAccount(deps, client, org, user) {
|
|
130
|
+
const idpId = platformClientSubject(org, user.externalUserId);
|
|
131
|
+
const existing = await findAccount(deps, idpId);
|
|
132
|
+
if (existing !== undefined) {
|
|
133
|
+
return platformClientAccountId(existing, user, org);
|
|
134
|
+
}
|
|
135
|
+
const spec = client.spec;
|
|
136
|
+
if (spec?.autoProvisionAccounts !== true) {
|
|
137
|
+
throw new ConnectError(noAccountMessage(user.externalUserId, org), Code.FailedPrecondition);
|
|
138
|
+
}
|
|
139
|
+
const input = accountInput(idpId, org, user);
|
|
140
|
+
const actor = serverActingFor(client.metadata?.id ?? "");
|
|
141
|
+
if (spec.autoGrantOnOrg) {
|
|
142
|
+
await grantAutoRole(deps, client, org, accountIdFor(idpId), actor);
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const created = await deps.createAccount(input, actor);
|
|
146
|
+
return created.metadata?.id ?? "";
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
const winner = await resolveCreateRace(error, () => deps.accounts.findByIdpId(idpId));
|
|
150
|
+
return platformClientAccountId(winner, user, org);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** The account under the subject, any mode; a store fault is INTERNAL, never "no account". */
|
|
154
|
+
async function findAccount(deps, idpId) {
|
|
155
|
+
try {
|
|
156
|
+
return await deps.accounts.findByIdpId(idpId);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
throw internalError(error, "failed to resolve platform client user");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The account's id, when a platform client provisioned it: a row under a
|
|
164
|
+
* `stgm_pc|` subject in any other mode is refused rather than minted for.
|
|
165
|
+
*/
|
|
166
|
+
function platformClientAccountId(account, user, org) {
|
|
167
|
+
if (account.spec?.provisioningMode !==
|
|
168
|
+
IdentityAccountProvisioningMode.platform_client) {
|
|
169
|
+
throw new ConnectError(foreignAccountMessage(user.externalUserId, org), Code.FailedPrecondition);
|
|
170
|
+
}
|
|
171
|
+
return account.metadata?.id ?? "";
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* The account the create path will write, validated now so no grant is
|
|
175
|
+
* written for a user the chain would refuse. The cloud's shape: named by
|
|
176
|
+
* the email, else the external id; first and last name split from the
|
|
177
|
+
* display name at its first space, else the email's local part.
|
|
178
|
+
*/
|
|
179
|
+
function accountInput(idpId, org, user) {
|
|
180
|
+
const input = {
|
|
181
|
+
name: user.email !== "" ? user.email : user.externalUserId,
|
|
182
|
+
spec: create(IdentityAccountSpecSchema, {
|
|
183
|
+
idpId,
|
|
184
|
+
email: user.email,
|
|
185
|
+
...splitName(user.name, user.email),
|
|
186
|
+
}),
|
|
187
|
+
provisioning: { mode: "platform_client", org },
|
|
188
|
+
};
|
|
189
|
+
const result = validator().validate(IdentityAccountSchema, create(IdentityAccountSchema, {
|
|
190
|
+
apiVersion: "iam.stigmer.ai/v1",
|
|
191
|
+
kind: "IdentityAccount",
|
|
192
|
+
metadata: { name: input.name, org },
|
|
193
|
+
spec: input.spec,
|
|
194
|
+
}));
|
|
195
|
+
if (result.kind === "invalid") {
|
|
196
|
+
throw new ConnectError(result.error.message, Code.InvalidArgument);
|
|
197
|
+
}
|
|
198
|
+
if (result.kind === "error") {
|
|
199
|
+
throw new ConnectError(`validation could not run: ${result.error.message}`, Code.Internal);
|
|
200
|
+
}
|
|
201
|
+
return input;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Grants the client's auto-grant role on the owning organization to the
|
|
205
|
+
* derived account id, as the client. Owner is refused here too: the
|
|
206
|
+
* contract refuses it on every write since this release, and a row stored
|
|
207
|
+
* before that must still never make an end user an owner.
|
|
208
|
+
*/
|
|
209
|
+
async function grantAutoRole(deps, client, org, accountId, actor) {
|
|
210
|
+
const configured = client.spec?.autoGrantRole ?? IamRole.iam_role_unspecified;
|
|
211
|
+
if (configured === IamRole.owner) {
|
|
212
|
+
throw new ConnectError(OWNER_AUTO_GRANT_MESSAGE, Code.InvalidArgument);
|
|
213
|
+
}
|
|
214
|
+
const role = configured === IamRole.iam_role_unspecified
|
|
215
|
+
? DEFAULT_AUTO_GRANT_ROLE
|
|
216
|
+
: configured;
|
|
217
|
+
try {
|
|
218
|
+
await deps.grantPath.grant(organizationRole(accountId, role, org), actor);
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
deps.logger.error("platform client auto-grant failed; nothing was provisioned", {
|
|
222
|
+
accountId,
|
|
223
|
+
platformClientId: client.metadata?.id ?? "",
|
|
224
|
+
error: error instanceof Error ? error.message : String(error),
|
|
225
|
+
});
|
|
226
|
+
throw new ConnectError(PROVISIONING_FAILED_MESSAGE, Code.Internal);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/** `stgm_pc|<org>|<user_id>`, each part non-blank and free of the separator. */
|
|
230
|
+
export function platformClientSubject(org, externalUserId) {
|
|
231
|
+
requireSubjectPart("org", org);
|
|
232
|
+
requireSubjectPart("externalUserId", externalUserId);
|
|
233
|
+
return `${PLATFORM_CLIENT_SUBJECT_PREFIX}${org}${SUBJECT_SEPARATOR}${externalUserId}`;
|
|
234
|
+
}
|
|
235
|
+
function requireSubjectPart(part, value) {
|
|
236
|
+
if (value.trim() === "") {
|
|
237
|
+
throw new ConnectError(blankSubjectPartMessage(part), Code.InvalidArgument);
|
|
238
|
+
}
|
|
239
|
+
if (value.includes(SUBJECT_SEPARATOR)) {
|
|
240
|
+
throw new ConnectError(subjectSeparatorMessage(part, value), Code.InvalidArgument);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/** The cloud's name split: the display name at its first space, else the email's local part. */
|
|
244
|
+
function splitName(name, email) {
|
|
245
|
+
if (name !== "") {
|
|
246
|
+
const space = name.indexOf(" ");
|
|
247
|
+
return space > 0
|
|
248
|
+
? { firstName: name.slice(0, space), lastName: name.slice(space + 1) }
|
|
249
|
+
: { firstName: name, lastName: "" };
|
|
250
|
+
}
|
|
251
|
+
const at = email.indexOf("@");
|
|
252
|
+
return { firstName: at >= 0 ? email.slice(0, at) : email, lastName: "" };
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=mint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mint.js","sourceRoot":"","sources":["../../../src/domain/platformclient/mint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Logger } from "../../boot/logger.js";
|
|
2
|
+
import type { CallerGuard } from "../../extensions/caller-guards.js";
|
|
3
|
+
import type { PlatformClientStore } from "./store.js";
|
|
4
|
+
export interface PlatformClientOriginGuardDeps {
|
|
5
|
+
readonly clients: Pick<PlatformClientStore, "findById">;
|
|
6
|
+
readonly logger: Logger;
|
|
7
|
+
}
|
|
8
|
+
export declare function newPlatformClientOriginGuard(deps: PlatformClientOriginGuardDeps): CallerGuard;
|
|
9
|
+
//# sourceMappingURL=origin-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"origin-guard.d.ts","sourceRoot":"","sources":["../../../src/domain/platformclient/origin-guard.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAYrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAKtD,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAC;IACxD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,6BAA6B,GAClC,WAAW,CAmCb"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PlatformClient origin guard: a request bearing a user token minted by
|
|
3
|
+
* a client that lists `allowed_origins` must come from one of them. The
|
|
4
|
+
* check needs the request's headers, which a verifier never sees, so it is
|
|
5
|
+
* a caller guard (extensions/caller-guards.ts) — open source's own,
|
|
6
|
+
* composed before any extension's.
|
|
7
|
+
*
|
|
8
|
+
* The rule, the cloud's since the Java service (spec.proto's field doc):
|
|
9
|
+
* - no `Origin` header, or a blank one: allowed — only browsers send
|
|
10
|
+
* Origin, and the control is a browser-context defense against a
|
|
11
|
+
* leaked token replayed from another site's page. The guard reads no
|
|
12
|
+
* client for such a request, so server-to-server callers pay nothing;
|
|
13
|
+
* - an empty `allowed_origins`: allowed (open mode);
|
|
14
|
+
* - otherwise the origin must match an entry case-insensitively (RFC 6454
|
|
15
|
+
* comparison), and the opaque origin "null" never matches.
|
|
16
|
+
* A refusal is PERMISSION_DENIED with the cloud's copy, logged with the
|
|
17
|
+
* procedure, the client and the origin.
|
|
18
|
+
*
|
|
19
|
+
* Only the untyped user token is the guard's: the claims are read from the
|
|
20
|
+
* token the verifier chain already verified on this request (the pattern
|
|
21
|
+
* caller-guards.ts prescribes), and any other credential — an API key, an
|
|
22
|
+
* OIDC token, a typed platform token — passes untouched. Liveness is not
|
|
23
|
+
* re-checked here beyond the one read the origin needs: the verifier
|
|
24
|
+
* refused a deleted client already, and a client deleted since is refused
|
|
25
|
+
* the same way, fail closed.
|
|
26
|
+
*/
|
|
27
|
+
import { Code, ConnectError } from "@connectrpc/connect";
|
|
28
|
+
import { TOKEN_TYPE_CLAIM, decodeVerifiedPlatformTokenPayload, stringClaim, } from "../../platformtoken/envelope.js";
|
|
29
|
+
import { DELETED_CLIENT_MESSAGE, USER_TOKEN_CLAIMS, originRefusalMessage, } from "./constants.js";
|
|
30
|
+
/** The opaque-origin serialization, which never matches a listed origin. */
|
|
31
|
+
const OPAQUE_ORIGIN = "null";
|
|
32
|
+
export function newPlatformClientOriginGuard(deps) {
|
|
33
|
+
return {
|
|
34
|
+
name: "platform-client-origin",
|
|
35
|
+
async guard(caller, method, headers) {
|
|
36
|
+
const origin = headers.get("origin") ?? "";
|
|
37
|
+
if (origin.trim() === "") {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const platformClientId = mintingClientOf(caller);
|
|
41
|
+
if (platformClientId === undefined) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const procedure = `/${method.parent.typeName}/${method.name}`;
|
|
45
|
+
const client = await deps.clients.findById(platformClientId);
|
|
46
|
+
if (client === undefined) {
|
|
47
|
+
throw new ConnectError(DELETED_CLIENT_MESSAGE, Code.Unauthenticated);
|
|
48
|
+
}
|
|
49
|
+
if (originAllowed(origin, client.spec?.allowedOrigins ?? [])) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
deps.logger.warn("origin refusal: origin not in allowed_origins", {
|
|
53
|
+
procedure,
|
|
54
|
+
platformClientId,
|
|
55
|
+
origin,
|
|
56
|
+
});
|
|
57
|
+
throw new ConnectError(originRefusalMessage(origin), Code.PermissionDenied);
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** The minting client of an untyped platform user token; undefined for every other credential. */
|
|
62
|
+
function mintingClientOf(caller) {
|
|
63
|
+
const payload = decodeVerifiedPlatformTokenPayload(caller.rawToken);
|
|
64
|
+
if (payload === undefined ||
|
|
65
|
+
stringClaim(payload, TOKEN_TYPE_CLAIM) !== undefined) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
return stringClaim(payload, USER_TOKEN_CLAIMS.platformClientId);
|
|
69
|
+
}
|
|
70
|
+
/** The cloud's origin rule for a non-blank Origin (see the header). */
|
|
71
|
+
function originAllowed(origin, allowed) {
|
|
72
|
+
if (allowed.length === 0) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
if (origin === OPAQUE_ORIGIN) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const presented = origin.toLowerCase();
|
|
79
|
+
return allowed.some((entry) => entry.toLowerCase() === presented);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=origin-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"origin-guard.js","sourceRoot":"","sources":["../../../src/domain/platformclient/origin-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAMzD,OAAO,EACL,gBAAgB,EAChB,kCAAkC,EAClC,WAAW,GACZ,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAGxB,4EAA4E;AAC5E,MAAM,aAAa,GAAG,MAAM,CAAC;AAO7B,MAAM,UAAU,4BAA4B,CAC1C,IAAmC;IAEnC,OAAO;QACL,IAAI,EAAE,wBAAwB;QAC9B,KAAK,CAAC,KAAK,CACT,MAAsB,EACtB,MAAkB,EAClB,OAAgB;YAEhB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;gBACzB,OAAO;YACT,CAAC;YACD,MAAM,gBAAgB,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;YACjD,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACnC,OAAO;YACT,CAAC;YACD,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAC9D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;YAC7D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,IAAI,YAAY,CAAC,sBAAsB,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,cAAc,IAAI,EAAE,CAAC,EAAE,CAAC;gBAC7D,OAAO;YACT,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+CAA+C,EAAE;gBAChE,SAAS;gBACT,gBAAgB;gBAChB,MAAM;aACP,CAAC,CAAC;YACH,MAAM,IAAI,YAAY,CACpB,oBAAoB,CAAC,MAAM,CAAC,EAC5B,IAAI,CAAC,gBAAgB,CACtB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,SAAS,eAAe,CAAC,MAAsB;IAC7C,MAAM,OAAO,GAAG,kCAAkC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpE,IACE,OAAO,KAAK,SAAS;QACrB,WAAW,CAAC,OAAO,EAAE,gBAAgB,CAAC,KAAK,SAAS,EACpD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,WAAW,CAAC,OAAO,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;AAClE,CAAC;AAED,uEAAuE;AACvE,SAAS,aAAa,CACpB,MAAc,EACd,OAA8B;IAE9B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACvC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-store.d.ts","sourceRoot":"","sources":["../../../src/domain/platformclient/resource-store.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAItD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,KAAK,GACX,mBAAmB,CA0GrB"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The open-source PlatformClientStore: the port (store.ts) over the
|
|
3
|
+
* generic Store, rows of the `resources` table by kind. The composition
|
|
4
|
+
* root installs it when no extension registers `drivers.platformClientStore`.
|
|
5
|
+
*
|
|
6
|
+
* `findById` is a primary-key read, the one lookup on a per-request path
|
|
7
|
+
* (the verifier's liveness read, the origin guard). The other three scan
|
|
8
|
+
* the kind: `findByClientId` through Store.findByField (ApiKey's lookup,
|
|
9
|
+
* domain/apikey/lookup.ts: a decode-and-scan per mint, watched by
|
|
10
|
+
* stigmer#987), `findByOrg` by listing the kind, and `findByOrgAndSlug`
|
|
11
|
+
* over that listing — an exact pair, unlike the shared slug helper, whose
|
|
12
|
+
* empty org matches every organization. A
|
|
13
|
+
* PlatformClient census is a handful of rows per organization, and none of
|
|
14
|
+
* the three sits on a per-request path.
|
|
15
|
+
*
|
|
16
|
+
* `save` and `update` are read-then-write because the generic Store's
|
|
17
|
+
* saveResource is an upsert with neither a create-only nor an update-only
|
|
18
|
+
* form — the identity-account adapter's posture, with its reasoning
|
|
19
|
+
* (domain/identityaccount/resource-store.ts): `save` refuses a held id,
|
|
20
|
+
* (org, slug) or client_id; `update` writes nothing for an unknown id; the
|
|
21
|
+
* residual window between the read and the write is the platform-wide
|
|
22
|
+
* CheckDuplicate-then-upsert window, not this adapter's to close.
|
|
23
|
+
*
|
|
24
|
+
* Store faults follow the ratified mapping: a typed ResourceNotFoundError
|
|
25
|
+
* reads as `undefined`; anything else propagates — an outage must never
|
|
26
|
+
* read as "no client", which on the verifier's path would revoke every
|
|
27
|
+
* live token.
|
|
28
|
+
*/
|
|
29
|
+
import { fromBinary } from "@bufbuild/protobuf";
|
|
30
|
+
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
31
|
+
import { PlatformClientSchema } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
32
|
+
import { ResourceNotFoundError } from "../../store/interface.js";
|
|
33
|
+
import { DuplicatePlatformClientError } from "./store.js";
|
|
34
|
+
const KIND = ApiResourceKind.platform_client;
|
|
35
|
+
export function newResourcePlatformClientStore(store) {
|
|
36
|
+
async function readById(id) {
|
|
37
|
+
try {
|
|
38
|
+
return await store.getResource(KIND, id, PlatformClientSchema);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error instanceof ResourceNotFoundError) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function readByClientId(clientId) {
|
|
48
|
+
if (clientId === "") {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
return await store.findByField(KIND, "spec.clientId", clientId, PlatformClientSchema);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (error instanceof ResourceNotFoundError) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Every client of the organization; a row that does not decode is skipped, as every scan does. */
|
|
62
|
+
async function listOrg(org) {
|
|
63
|
+
const clients = [];
|
|
64
|
+
for (const data of await store.listResources(KIND)) {
|
|
65
|
+
let client;
|
|
66
|
+
try {
|
|
67
|
+
client = fromBinary(PlatformClientSchema, data);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if ((client.metadata?.org ?? "") === org) {
|
|
73
|
+
clients.push(client);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return clients;
|
|
77
|
+
}
|
|
78
|
+
/** The exact (org, slug) pair — an empty org is no wildcard here. */
|
|
79
|
+
async function readByOrgAndSlug(org, slug) {
|
|
80
|
+
if (org === "" || slug === "") {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
return (await listOrg(org)).find((client) => (client.metadata?.slug ?? "") === slug);
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
async save(client) {
|
|
87
|
+
const id = client.metadata?.id ?? "";
|
|
88
|
+
const org = client.metadata?.org ?? "";
|
|
89
|
+
const slug = client.metadata?.slug ?? "";
|
|
90
|
+
if ((await readById(id)) !== undefined) {
|
|
91
|
+
throw new DuplicatePlatformClientError(`platform client '${id}' already exists`);
|
|
92
|
+
}
|
|
93
|
+
if ((await readByOrgAndSlug(org, slug)) !== undefined) {
|
|
94
|
+
throw new DuplicatePlatformClientError(`platform client '${org}/${slug}' already exists`);
|
|
95
|
+
}
|
|
96
|
+
if ((await readByClientId(client.spec?.clientId ?? "")) !== undefined) {
|
|
97
|
+
throw new DuplicatePlatformClientError("a platform client already holds this client_id");
|
|
98
|
+
}
|
|
99
|
+
await store.saveResource(KIND, id, PlatformClientSchema, client);
|
|
100
|
+
},
|
|
101
|
+
async update(client) {
|
|
102
|
+
const id = client.metadata?.id ?? "";
|
|
103
|
+
if ((await readById(id)) === undefined) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
await store.saveResource(KIND, id, PlatformClientSchema, client);
|
|
107
|
+
},
|
|
108
|
+
async deleteById(id) {
|
|
109
|
+
await store.deleteResource(KIND, id);
|
|
110
|
+
},
|
|
111
|
+
findById: readById,
|
|
112
|
+
findByClientId: readByClientId,
|
|
113
|
+
findByOrgAndSlug: readByOrgAndSlug,
|
|
114
|
+
findByOrg: listOrg,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=resource-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-store.js","sourceRoot":"","sources":["../../../src/domain/platformclient/resource-store.ts"],"names":[],"mappings":"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"}
|