pyric-admin 0.1.0-alpha.30 → 0.1.0-alpha.30.1

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.
@@ -40,6 +40,11 @@ export declare function applicationDefault(): never;
40
40
  * Link-compatible mirror of `firebase-admin/app`'s `cert(serviceAccountPathOrObject)`.
41
41
  * Returns an inert sandbox credential token so unchanged application setup code
42
42
  * can assign `appOptions.credential = cert(...)` under `@pyric/cli/register`.
43
+ *
44
+ * It keeps one field, the service account's project id, because firebase-admin
45
+ * finds an app's project there when the options name none. A path is read as a
46
+ * JSON file; a file that is missing, unreadable, or has no project id gives a
47
+ * credential without one, and never throws, so apps run without a key on disk.
43
48
  */
44
49
  export declare function cert(serviceAccountPathOrObject: unknown): object;
45
50
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/app/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAIL,KAAK,OAAO,EACb,MAAM,eAAe,CAAC;AAMvB,gDAAgD;AAChD,eAAO,MAAM,gBAAgB,eAAuC,CAAC;AACrE,MAAM,MAAM,mBAAmB,GAAG,SAAS,CAAC;AAE5C,yCAAyC;AACzC,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,CAAC,gBAAgB,CAAC,EAAE,SAAS,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;CACnC;AAED,sLAAsL;AACtL,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,aAAa,GAAG,eAAe,CAAC;AAC5C,MAAM,MAAM,wBAAwB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,eAAe,CAAC;AAE9E;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,KAAK,CAK1C;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,0BAA0B,EAAE,OAAO,GAAG,MAAM,CAEhE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,wBAAwB,EAAE,OAAO,GAAG,MAAM,CAEtE;AA4CD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,CAAC,EAAE,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,IAAI,GAAE,MAAyB,GAC9B,aAAa,CAmCf;AAED,4CAA4C;AAC5C,wBAAgB,MAAM,CAAC,IAAI,GAAE,MAAyB,GAAG,aAAa,CAarE;AAED,yCAAyC;AACzC,wBAAgB,OAAO,IAAI,aAAa,EAAE,CAEzC;AAED,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAS3D;AAwED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,GAAG,IAAI,eAAe,CAE5E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/app/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAIL,KAAK,OAAO,EACb,MAAM,eAAe,CAAC;AAOvB,gDAAgD;AAChD,eAAO,MAAM,gBAAgB,eAAuC,CAAC;AACrE,MAAM,MAAM,mBAAmB,GAAG,SAAS,CAAC;AAE5C,yCAAyC;AACzC,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,CAAC,gBAAgB,CAAC,EAAE,SAAS,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;CACnC;AAED,sLAAsL;AACtL,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,aAAa,GAAG,eAAe,CAAC;AAC5C,MAAM,MAAM,wBAAwB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,eAAe,CAAC;AAE9E;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,KAAK,CAK1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,0BAA0B,EAAE,OAAO,GAAG,MAAM,CAIhE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,wBAAwB,EAAE,OAAO,GAAG,MAAM,CAEtE;AA4CD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,CAAC,EAAE,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,IAAI,GAAE,MAAyB,GAC9B,aAAa,CAqCf;AAED,4CAA4C;AAC5C,wBAAgB,MAAM,CAAC,IAAI,GAAE,MAAyB,GAAG,aAAa,CAarE;AAED,yCAAyC;AACzC,wBAAgB,OAAO,IAAI,aAAa,EAAE,CAEzC;AAED,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAS3D;AAwED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,GAAG,IAAI,eAAe,CAE5E"}
package/dist/app/index.js CHANGED
@@ -9,6 +9,7 @@ import { REMOTE_SANDBOX_FACTORY, } from 'pyric/sandbox';
9
9
  import { parsePyricSandbox, processActivation } from 'pyric/sandbox/internal';
10
10
  import { readFileSync } from 'node:fs';
11
11
  import { assertAdminAppActive, markAdminAppDeleted } from './lifecycle.js';
12
+ import { keepAppCredentialProjectId, keepCredentialProjectId } from './project-id.js';
12
13
  /** Brand carried by every sandbox admin app. */
13
14
  export const ADMIN_APP_TARGET = Symbol.for('pyric.admin.app.target');
14
15
  /** firebase-admin's default app name. */
@@ -28,9 +29,16 @@ export function applicationDefault() {
28
29
  * Link-compatible mirror of `firebase-admin/app`'s `cert(serviceAccountPathOrObject)`.
29
30
  * Returns an inert sandbox credential token so unchanged application setup code
30
31
  * can assign `appOptions.credential = cert(...)` under `@pyric/cli/register`.
32
+ *
33
+ * It keeps one field, the service account's project id, because firebase-admin
34
+ * finds an app's project there when the options name none. A path is read as a
35
+ * JSON file; a file that is missing, unreadable, or has no project id gives a
36
+ * credential without one, and never throws, so apps run without a key on disk.
31
37
  */
32
38
  export function cert(serviceAccountPathOrObject) {
33
- return { [Symbol.for('pyric.admin.credential')]: 'cert' };
39
+ const credential = { [Symbol.for('pyric.admin.credential')]: 'cert' };
40
+ keepCredentialProjectId(credential, serviceAccountPathOrObject);
41
+ return credential;
34
42
  }
35
43
  /**
36
44
  * Link-compatible mirror of `firebase-admin/app`'s `refreshToken(refreshTokenPathOrObject)`.
@@ -87,6 +95,7 @@ export function initializeApp(config, name = DEFAULT_APP_NAME) {
87
95
  throw alreadyExists(name, 'invalid-app-options');
88
96
  }
89
97
  const app = initializeAmbientApp(name, ambientAppOptions(config));
98
+ keepAppCredentialProjectId(app, config);
90
99
  appRegistry.set(name, app);
91
100
  ambientApps.add(app);
92
101
  return app;
@@ -102,6 +111,7 @@ export function initializeApp(config, name = DEFAULT_APP_NAME) {
102
111
  name,
103
112
  options: appOptionsFrom(config),
104
113
  };
114
+ keepAppCredentialProjectId(app, config);
105
115
  appRegistry.set(name, app);
106
116
  return app;
107
117
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/app/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/app/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /** Keeps the service account's project id on an inert credential, as a non-enumerable property. */
2
+ export declare function keepCredentialProjectId(credential: object, serviceAccountPathOrObject: unknown): void;
3
+ /** Copies a cert credential's project id from initialization options onto the app, beside `options`. */
4
+ export declare function keepAppCredentialProjectId(app: object, config: unknown): void;
5
+ /** firebase-admin's `getExplicitProjectId` for a sandbox admin app. */
6
+ export declare function explicitProjectId(app: {
7
+ readonly options: {
8
+ readonly projectId?: string;
9
+ };
10
+ }): string | undefined;
11
+ //# sourceMappingURL=project-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-id.d.ts","sourceRoot":"","sources":["../../src/app/project-id.ts"],"names":[],"mappings":"AA4CA,mGAAmG;AACnG,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,0BAA0B,EAAE,OAAO,GAAG,IAAI,CAGrG;AAED,wGAAwG;AACxG,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAM7E;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAMhH"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The project id an admin app resolves, in firebase-admin's order
3
+ * (`getExplicitProjectId`, firebase-admin 13 `lib/utils/index.js`): the
4
+ * `projectId` app option, then a cert credential's project id, then
5
+ * `GOOGLE_CLOUD_PROJECT`, then `GCLOUD_PROJECT`.
6
+ *
7
+ * Pyric's `cert()` is inert: it keeps the service account's project id and
8
+ * nothing else, so no private key or client email is held in the sandbox.
9
+ * Both keys sit behind `Symbol.for`, as the app registry does, so the require
10
+ * and import copies of this module that the register hook can load agree.
11
+ */
12
+ import { readFileSync } from 'node:fs';
13
+ const CREDENTIAL_PROJECT_ID = Symbol.for('pyric.admin.credential.projectId');
14
+ const APP_CREDENTIAL_PROJECT_ID = Symbol.for('pyric.admin.app.credentialProjectId');
15
+ function nonEmptyString(value) {
16
+ return typeof value === 'string' && value !== '' ? value : undefined;
17
+ }
18
+ /** firebase-admin's `ServiceAccount.fromPath`, except that a file it cannot read or parse yields no object. */
19
+ function readServiceAccountFile(path) {
20
+ try {
21
+ return JSON.parse(readFileSync(path, 'utf8'));
22
+ }
23
+ catch {
24
+ return undefined;
25
+ }
26
+ }
27
+ /** The project id of a service account object or file path: `projectId`, then `project_id`, as firebase-admin's `copyAttr` reads it. */
28
+ function serviceAccountProjectId(serviceAccountPathOrObject) {
29
+ const isPath = typeof serviceAccountPathOrObject === 'string';
30
+ const account = isPath ? readServiceAccountFile(serviceAccountPathOrObject) : serviceAccountPathOrObject;
31
+ if (typeof account !== 'object' || account === null)
32
+ return undefined;
33
+ const { projectId, project_id: projectIdSnake } = account;
34
+ return nonEmptyString(projectId) ?? nonEmptyString(projectIdSnake);
35
+ }
36
+ function defineHidden(target, key, value) {
37
+ Object.defineProperty(target, key, { value, enumerable: false, writable: false, configurable: false });
38
+ }
39
+ /** Keeps the service account's project id on an inert credential, as a non-enumerable property. */
40
+ export function keepCredentialProjectId(credential, serviceAccountPathOrObject) {
41
+ const projectId = serviceAccountProjectId(serviceAccountPathOrObject);
42
+ if (projectId !== undefined)
43
+ defineHidden(credential, CREDENTIAL_PROJECT_ID, projectId);
44
+ }
45
+ /** Copies a cert credential's project id from initialization options onto the app, beside `options`. */
46
+ export function keepAppCredentialProjectId(app, config) {
47
+ if (typeof config !== 'object' || config === null)
48
+ return;
49
+ const credential = config.credential;
50
+ if (typeof credential !== 'object' || credential === null)
51
+ return;
52
+ const projectId = nonEmptyString(credential[CREDENTIAL_PROJECT_ID]);
53
+ if (projectId !== undefined)
54
+ defineHidden(app, APP_CREDENTIAL_PROJECT_ID, projectId);
55
+ }
56
+ /** firebase-admin's `getExplicitProjectId` for a sandbox admin app. */
57
+ export function explicitProjectId(app) {
58
+ return (nonEmptyString(app.options.projectId) ??
59
+ nonEmptyString(app[APP_CREDENTIAL_PROJECT_ID]) ??
60
+ nonEmptyString(process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT));
61
+ }
62
+ //# sourceMappingURL=project-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-id.js","sourceRoot":"","sources":["../../src/app/project-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,qBAAqB,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAC7E,MAAM,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;AAIpF,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvE,CAAC;AAED,+GAA+G;AAC/G,SAAS,sBAAsB,CAAC,IAAY;IAC1C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,wIAAwI;AACxI,SAAS,uBAAuB,CAAC,0BAAmC;IAClE,MAAM,MAAM,GAAG,OAAO,0BAA0B,KAAK,QAAQ,CAAC;IAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC;IACzG,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACtE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,OAAkC,CAAC;IACrF,OAAO,cAAc,CAAC,SAAS,CAAC,IAAI,cAAc,CAAC,cAAc,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,YAAY,CAAC,MAAc,EAAE,GAAW,EAAE,KAAa;IAC9D,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;AACzG,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,uBAAuB,CAAC,UAAkB,EAAE,0BAAmC;IAC7F,MAAM,SAAS,GAAG,uBAAuB,CAAC,0BAA0B,CAAC,CAAC;IACtE,IAAI,SAAS,KAAK,SAAS;QAAE,YAAY,CAAC,UAAU,EAAE,qBAAqB,EAAE,SAAS,CAAC,CAAC;AAC1F,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,0BAA0B,CAAC,GAAW,EAAE,MAAe;IACrE,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO;IAC1D,MAAM,UAAU,GAAI,MAAmC,CAAC,UAAU,CAAC;IACnE,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO;IAClE,MAAM,SAAS,GAAG,cAAc,CAAE,UAA4B,CAAC,qBAAqB,CAAC,CAAC,CAAC;IACvF,IAAI,SAAS,KAAK,SAAS;QAAE,YAAY,CAAC,GAAG,EAAE,yBAAyB,EAAE,SAAS,CAAC,CAAC;AACvF,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,iBAAiB,CAAC,GAA0D;IAC1F,OAAO,CACL,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;QACrC,cAAc,CAAE,GAAqB,CAAC,yBAAyB,CAAC,CAAC;QACjE,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAC/E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { PrefixedFirebaseError } from '../app/firebase-error.js';
2
+ export type AppCheckErrorCode = 'invalid-argument' | 'invalid-credential' | 'app-check-token-expired' | 'unknown-error';
3
+ /** firebase-admin's FirebaseAppCheckError: a PrefixedFirebaseError with prefix `app-check`. */
4
+ export declare class FirebaseAppCheckError extends PrefixedFirebaseError {
5
+ constructor(code: AppCheckErrorCode, message: string);
6
+ }
7
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/app-check/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,GAAG,oBAAoB,GAAG,yBAAyB,GAAG,eAAe,CAAC;AAExH,+FAA+F;AAC/F,qBAAa,qBAAsB,SAAQ,qBAAqB;gBAClD,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM;CAGrD"}
@@ -0,0 +1,8 @@
1
+ import { PrefixedFirebaseError } from '../app/firebase-error.js';
2
+ /** firebase-admin's FirebaseAppCheckError: a PrefixedFirebaseError with prefix `app-check`. */
3
+ export class FirebaseAppCheckError extends PrefixedFirebaseError {
4
+ constructor(code, message) {
5
+ super('app-check', code, message);
6
+ }
7
+ }
8
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/app-check/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAIjE,+FAA+F;AAC/F,MAAM,OAAO,qBAAsB,SAAQ,qBAAqB;IAC9D,YAAY,IAAuB,EAAE,OAAe;QAClD,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import type { VerifyAppCheckTokenResponse } from './index.js';
2
+ /**
3
+ * Verifies a token from Firebase with firebase-admin, through the verifier the
4
+ * register installs. Its result and its errors come back unchanged.
5
+ */
6
+ export declare function verifyFirebaseToken(token: string, projectId: string): Promise<VerifyAppCheckTokenResponse>;
7
+ //# sourceMappingURL=firebase-token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebase-token.d.ts","sourceRoot":"","sources":["../../src/app-check/firebase-token.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AA8B9D;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAShH"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * App Check tokens from Firebase: a token whose `kid` names a key that is not
3
+ * the sandbox's (#1552, #1301).
4
+ *
5
+ * In production AI mode the page's `firebase/app-check` is the Firebase SDK,
6
+ * so its tokens come from Firebase, and only firebase-admin's own verifier can
7
+ * check them. `@pyric/cli/register` installs that verifier behind
8
+ * {@link FIREBASE_VERIFIER} in production AI mode only, the same kind of seam
9
+ * as its `pyric.remote.sandboxFactory`: this package never learns what an AI
10
+ * mode is, and never loads firebase-admin itself.
11
+ *
12
+ * With no verifier installed the token is refused with a message that says
13
+ * why. The code stays `invalid-argument`, so a server that branches on it
14
+ * still answers 401.
15
+ */
16
+ import { FirebaseAppCheckError } from './error.js';
17
+ const FIREBASE_VERIFIER = Symbol.for('pyric.admin.appCheck.firebaseVerifier');
18
+ const MESSAGES = {
19
+ notSandbox: "This App Check token was not minted by the Pyric sandbox, so the sandbox's firebase-admin/app-check cannot verify it. " +
20
+ 'A page in production AI mode gets its App Check tokens from Firebase. Start this server in production AI mode too ' +
21
+ '(PYRIC_AI_MODE=production) and Pyric verifies them with firebase-admin. In sandbox AI mode, page tokens come from the sandbox and verify here.',
22
+ install: 'Production AI mode verifies App Check tokens from Firebase with firebase-admin, which is not installed beside this server. ' +
23
+ 'Install it in the project that runs the server (npm install firebase-admin) and restart.',
24
+ };
25
+ function installedVerifier() {
26
+ const verifier = globalThis[FIREBASE_VERIFIER];
27
+ return typeof verifier === 'function' ? verifier : undefined;
28
+ }
29
+ /** Whether a failure is the `firebase-admin` package itself not resolving, from ESM or CJS. */
30
+ function isFirebaseAdminMissing(error) {
31
+ const { code, message } = (error ?? {});
32
+ const isNotFound = code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND';
33
+ const namesFirebaseAdmin = typeof message === 'string' && /'firebase-admin[/']/.test(message);
34
+ return isNotFound && namesFirebaseAdmin;
35
+ }
36
+ /**
37
+ * Verifies a token from Firebase with firebase-admin, through the verifier the
38
+ * register installs. Its result and its errors come back unchanged.
39
+ */
40
+ export async function verifyFirebaseToken(token, projectId) {
41
+ const verifier = installedVerifier();
42
+ if (verifier === undefined)
43
+ throw new FirebaseAppCheckError('invalid-argument', MESSAGES.notSandbox);
44
+ try {
45
+ return await verifier(token, projectId);
46
+ }
47
+ catch (error) {
48
+ if (isFirebaseAdminMissing(error))
49
+ throw new FirebaseAppCheckError('invalid-argument', MESSAGES.install);
50
+ throw error;
51
+ }
52
+ }
53
+ //# sourceMappingURL=firebase-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebase-token.js","sourceRoot":"","sources":["../../src/app-check/firebase-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGnD,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;AAK9E,MAAM,QAAQ,GAAG;IACf,UAAU,EACR,wHAAwH;QACxH,oHAAoH;QACpH,gJAAgJ;IAClJ,OAAO,EACL,6HAA6H;QAC7H,0FAA0F;CAC7F,CAAC;AAEF,SAAS,iBAAiB;IACxB,MAAM,QAAQ,GAAI,UAAsC,CAAC,iBAAiB,CAAC,CAAC;IAC5E,OAAO,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAE,QAA6B,CAAC,CAAC,CAAC,SAAS,CAAC;AACrF,CAAC;AAED,+FAA+F;AAC/F,SAAS,sBAAsB,CAAC,KAAc;IAC5C,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAA0C,CAAC;IACjF,MAAM,UAAU,GAAG,IAAI,KAAK,sBAAsB,IAAI,IAAI,KAAK,kBAAkB,CAAC;IAClF,MAAM,kBAAkB,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9F,OAAO,UAAU,IAAI,kBAAkB,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAAa,EAAE,SAAiB;IACxE,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,IAAI,QAAQ,KAAK,SAAS;QAAE,MAAM,IAAI,qBAAqB,CAAC,kBAAkB,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACrG,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,sBAAsB,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,qBAAqB,CAAC,kBAAkB,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QACzG,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -10,6 +10,11 @@
10
10
  * One deliberate difference: the sandbox has no list of the project's
11
11
  * registered apps, so `createToken` accepts any app id (row
12
12
  * `app-check-admin#create-token-unknown-app`, diverged by design).
13
+ *
14
+ * A token whose `kid` is not the sandbox's came from Firebase. It goes to
15
+ * firebase-admin's own verifier when `@pyric/cli/register` installed one
16
+ * (production AI mode), and is refused with a message that says why otherwise
17
+ * (./firebase-token.ts).
13
18
  */
14
19
  import { type AppCheckTokenClaims } from 'pyric/sandbox/internal';
15
20
  import { type PyricAdminApp } from '../app/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/app-check/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAyC,KAAK,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAEzG,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAyC7D,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,oBAAoB,CAAC;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAgCD,qBAAa,QAAQ;;IAGnB,gBAAgB;gBACJ,GAAG,EAAE,aAAa;IAI9B,IAAI,GAAG,IAAI,aAAa,CAEvB;IAEK,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;IAUxF;;;;;OAKG;IACH,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,2BAA2B,CAAC;CAuC/G;AAoCD,wBAAgB,WAAW,CAAC,GAAG,CAAC,EAAE,aAAa,GAAG,QAAQ,CAQzD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/app-check/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAyC,KAAK,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACzG,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAiC7D,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,oBAAoB,CAAC;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAgCD,qBAAa,QAAQ;;IAGnB,gBAAgB;gBACJ,GAAG,EAAE,aAAa;IAI9B,IAAI,GAAG,IAAI,aAAa,CAEvB;IAEK,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;IAUxF;;;;;OAKG;IACH,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,2BAA2B,CAAC;CAqD/G;AAoCD,wBAAgB,WAAW,CAAC,GAAG,CAAC,EAAE,aAAa,GAAG,QAAQ,CAQzD"}
@@ -10,11 +10,18 @@
10
10
  * One deliberate difference: the sandbox has no list of the project's
11
11
  * registered apps, so `createToken` accepts any app id (row
12
12
  * `app-check-admin#create-token-unknown-app`, diverged by design).
13
+ *
14
+ * A token whose `kid` is not the sandbox's came from Firebase. It goes to
15
+ * firebase-admin's own verifier when `@pyric/cli/register` installed one
16
+ * (production AI mode), and is refused with a message that says why otherwise
17
+ * (./firebase-token.ts).
13
18
  */
14
19
  import { checkAppCheckToken, mintAppCheckToken } from 'pyric/sandbox/internal';
15
- import { PrefixedFirebaseError } from '../app/firebase-error.js';
16
20
  import { getApp } from '../app/index.js';
21
+ import { explicitProjectId } from '../app/project-id.js';
17
22
  import { assertAdminAppActive } from '../app/lifecycle.js';
23
+ import { FirebaseAppCheckError } from './error.js';
24
+ import { verifyFirebaseToken } from './firebase-token.js';
18
25
  const MINUTE_MILLIS = 60 * 1000;
19
26
  const MIN_TTL_MILLIS = 30 * MINUTE_MILLIS;
20
27
  const MAX_TTL_MILLIS = 7 * 24 * 60 * MINUTE_MILLIS;
@@ -25,7 +32,6 @@ const MESSAGES = {
25
32
  algorithm: (alg) => `The provided App Check token has incorrect algorithm. Expected "RS256" but got "${String(alg)}".`,
26
33
  noSub: 'The provided App Check token has no "sub" (subject) claim.',
27
34
  emptySub: 'The provided App Check token has an empty string "sub" (subject) claim.',
28
- noMatchingKid: 'The provided App Check token has "kid" claim which does not correspond to a known public key. Most likely the provided App Check token is expired, so get a fresh token from your client app and try again.',
29
35
  ttl: 'ttlMillis must be a duration in milliseconds between 30 minutes and 7 days (inclusive).',
30
36
  appId: '`appId` must be a non-empty string.',
31
37
  decode: 'Decoding App Check token failed. Make sure you passed the entire string JWT which represents the Firebase App Check token.',
@@ -37,12 +43,6 @@ const MESSAGES = {
37
43
  audience: (scoped, aud) => `The provided App Check token has incorrect "aud" (audience) claim. Expected "${scoped}" but got "${String(aud)}". Make sure the App Check token comes from the same Firebase project as the service account used to authenticate this SDK.`,
38
44
  };
39
45
  const APP_CHECK_ISSUER = 'https://firebaseappcheck.googleapis.com/';
40
- /** firebase-admin's FirebaseAppCheckError: a PrefixedFirebaseError with prefix `app-check`. */
41
- class FirebaseAppCheckError extends PrefixedFirebaseError {
42
- constructor(code, message) {
43
- super('app-check', code, message);
44
- }
45
- }
46
46
  /**
47
47
  * Consumed token ids, per sandbox handle, for this process. The map sits
48
48
  * behind Symbol.for, as the app registry in ../app/index.ts does, so the
@@ -84,7 +84,7 @@ export class AppCheck {
84
84
  if (typeof appId !== 'string' || appId.length === 0)
85
85
  throw new FirebaseAppCheckError('invalid-argument', MESSAGES.appId);
86
86
  const ttlMillis = ttlFrom(options);
87
- const projectId = this.#configuredProjectId();
87
+ const projectId = explicitProjectId(this.#app);
88
88
  if (!projectId)
89
89
  throw new FirebaseAppCheckError('unknown-error', MESSAGES.createNoProject);
90
90
  const minted = await mintAppCheckToken({ appId, projectId }, Math.floor(ttlMillis / 1000));
@@ -110,30 +110,40 @@ export class AppCheck {
110
110
  const check = await checkAppCheckToken(appCheckToken);
111
111
  if (!check.ok && check.reason === 'malformed')
112
112
  throw new FirebaseAppCheckError('invalid-argument', MESSAGES.decode);
113
+ // A kid that names a key other than the sandbox's: the token came from
114
+ // Firebase, so firebase-admin runs every check, in production's order.
115
+ const isFirebaseToken = !check.ok && check.reason === 'kid';
116
+ if (isFirebaseToken) {
117
+ const verified = await verifyFirebaseToken(appCheckToken, projectId);
118
+ return this.#recordConsume(verified, appCheckToken, options);
119
+ }
113
120
  verifyContent(check.header, check.claims, projectId);
114
- if (!check.ok && check.reason === 'kid')
115
- throw new FirebaseAppCheckError('invalid-argument', MESSAGES.noMatchingKid);
116
121
  if (!check.ok)
117
122
  throw new FirebaseAppCheckError('invalid-argument', MESSAGES.signature);
118
123
  verifyNotBefore(check.claims.nbf);
119
124
  verifyExpiry(check.claims.exp);
120
125
  const claims = check.claims;
121
126
  const result = { appId: claims.sub, token: { ...claims, app_id: claims.sub } };
122
- if (options?.consume) {
123
- const consumed = consumedFor(this.#app);
124
- const tokenId = typeof claims.jti === 'string' ? claims.jti : appCheckToken;
125
- result.alreadyConsumed = consumed.has(tokenId);
126
- consumed.add(tokenId);
127
- }
128
- return result;
127
+ return this.#recordConsume(result, appCheckToken, options);
129
128
  }
130
- /** The app's project, found where firebase-admin's findProjectId looks: the app options, then the environment. */
131
- #configuredProjectId() {
132
- return this.#app.options.projectId || process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT || undefined;
129
+ /**
130
+ * `consume: true` marks the token used, in this process, for sandbox and
131
+ * Firebase tokens alike. It is never forwarded to Firebase, which would need
132
+ * a credential with App Check permissions.
133
+ */
134
+ #recordConsume(result, appCheckToken, options) {
135
+ if (!options?.consume)
136
+ return result;
137
+ const consumed = consumedFor(this.#app);
138
+ const jti = result.token.jti;
139
+ const tokenId = typeof jti === 'string' ? jti : appCheckToken;
140
+ result.alreadyConsumed = consumed.has(tokenId);
141
+ consumed.add(tokenId);
142
+ return result;
133
143
  }
134
144
  /** The project a token must be scoped to, resolved as firebase-admin resolves it. */
135
145
  #projectId() {
136
- const projectId = this.#configuredProjectId();
146
+ const projectId = explicitProjectId(this.#app);
137
147
  if (!projectId)
138
148
  throw new FirebaseAppCheckError('invalid-credential', MESSAGES.noProject);
139
149
  return projectId;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/app-check/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/app-check/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pyric-admin",
3
- "version": "0.1.0-alpha.30",
3
+ "version": "0.1.0-alpha.30.1",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://pyric.dev",
6
6
  "repository": {
@@ -106,7 +106,7 @@
106
106
  "typecheck": "bun x tsc -p tsconfig.json --noEmit"
107
107
  },
108
108
  "dependencies": {
109
- "pyric": "^0.1.0-alpha.30"
109
+ "pyric": "^0.1.0-alpha.30.1"
110
110
  },
111
111
  "devDependencies": {
112
112
  "@types/bun": "1.3.14",
package/src/app/index.ts CHANGED
@@ -15,6 +15,7 @@ import { parsePyricSandbox, processActivation } from 'pyric/sandbox/internal';
15
15
  import { readFileSync } from 'node:fs';
16
16
 
17
17
  import { assertAdminAppActive, markAdminAppDeleted } from './lifecycle.js';
18
+ import { keepAppCredentialProjectId, keepCredentialProjectId } from './project-id.js';
18
19
 
19
20
  /** Brand carried by every sandbox admin app. */
20
21
  export const ADMIN_APP_TARGET = Symbol.for('pyric.admin.app.target');
@@ -59,9 +60,16 @@ export function applicationDefault(): never {
59
60
  * Link-compatible mirror of `firebase-admin/app`'s `cert(serviceAccountPathOrObject)`.
60
61
  * Returns an inert sandbox credential token so unchanged application setup code
61
62
  * can assign `appOptions.credential = cert(...)` under `@pyric/cli/register`.
63
+ *
64
+ * It keeps one field, the service account's project id, because firebase-admin
65
+ * finds an app's project there when the options name none. A path is read as a
66
+ * JSON file; a file that is missing, unreadable, or has no project id gives a
67
+ * credential without one, and never throws, so apps run without a key on disk.
62
68
  */
63
69
  export function cert(serviceAccountPathOrObject: unknown): object {
64
- return { [Symbol.for('pyric.admin.credential')]: 'cert' };
70
+ const credential = { [Symbol.for('pyric.admin.credential')]: 'cert' };
71
+ keepCredentialProjectId(credential, serviceAccountPathOrObject);
72
+ return credential;
65
73
  }
66
74
 
67
75
  /**
@@ -139,6 +147,7 @@ export function initializeApp(
139
147
  throw alreadyExists(name, 'invalid-app-options');
140
148
  }
141
149
  const app = initializeAmbientApp(name, ambientAppOptions(config));
150
+ keepAppCredentialProjectId(app, config);
142
151
  appRegistry.set(name, app);
143
152
  ambientApps.add(app);
144
153
  return app;
@@ -158,6 +167,7 @@ export function initializeApp(
158
167
  name,
159
168
  options: appOptionsFrom(config),
160
169
  };
170
+ keepAppCredentialProjectId(app, config);
161
171
  appRegistry.set(name, app);
162
172
  return app;
163
173
  }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The project id an admin app resolves, in firebase-admin's order
3
+ * (`getExplicitProjectId`, firebase-admin 13 `lib/utils/index.js`): the
4
+ * `projectId` app option, then a cert credential's project id, then
5
+ * `GOOGLE_CLOUD_PROJECT`, then `GCLOUD_PROJECT`.
6
+ *
7
+ * Pyric's `cert()` is inert: it keeps the service account's project id and
8
+ * nothing else, so no private key or client email is held in the sandbox.
9
+ * Both keys sit behind `Symbol.for`, as the app registry does, so the require
10
+ * and import copies of this module that the register hook can load agree.
11
+ */
12
+ import { readFileSync } from 'node:fs';
13
+
14
+ const CREDENTIAL_PROJECT_ID = Symbol.for('pyric.admin.credential.projectId');
15
+ const APP_CREDENTIAL_PROJECT_ID = Symbol.for('pyric.admin.app.credentialProjectId');
16
+
17
+ type WithProjectId = { [CREDENTIAL_PROJECT_ID]?: unknown; [APP_CREDENTIAL_PROJECT_ID]?: unknown };
18
+
19
+ function nonEmptyString(value: unknown): string | undefined {
20
+ return typeof value === 'string' && value !== '' ? value : undefined;
21
+ }
22
+
23
+ /** firebase-admin's `ServiceAccount.fromPath`, except that a file it cannot read or parse yields no object. */
24
+ function readServiceAccountFile(path: string): unknown {
25
+ try {
26
+ return JSON.parse(readFileSync(path, 'utf8'));
27
+ } catch {
28
+ return undefined;
29
+ }
30
+ }
31
+
32
+ /** The project id of a service account object or file path: `projectId`, then `project_id`, as firebase-admin's `copyAttr` reads it. */
33
+ function serviceAccountProjectId(serviceAccountPathOrObject: unknown): string | undefined {
34
+ const isPath = typeof serviceAccountPathOrObject === 'string';
35
+ const account = isPath ? readServiceAccountFile(serviceAccountPathOrObject) : serviceAccountPathOrObject;
36
+ if (typeof account !== 'object' || account === null) return undefined;
37
+ const { projectId, project_id: projectIdSnake } = account as Record<string, unknown>;
38
+ return nonEmptyString(projectId) ?? nonEmptyString(projectIdSnake);
39
+ }
40
+
41
+ function defineHidden(target: object, key: symbol, value: string): void {
42
+ Object.defineProperty(target, key, { value, enumerable: false, writable: false, configurable: false });
43
+ }
44
+
45
+ /** Keeps the service account's project id on an inert credential, as a non-enumerable property. */
46
+ export function keepCredentialProjectId(credential: object, serviceAccountPathOrObject: unknown): void {
47
+ const projectId = serviceAccountProjectId(serviceAccountPathOrObject);
48
+ if (projectId !== undefined) defineHidden(credential, CREDENTIAL_PROJECT_ID, projectId);
49
+ }
50
+
51
+ /** Copies a cert credential's project id from initialization options onto the app, beside `options`. */
52
+ export function keepAppCredentialProjectId(app: object, config: unknown): void {
53
+ if (typeof config !== 'object' || config === null) return;
54
+ const credential = (config as { credential?: unknown }).credential;
55
+ if (typeof credential !== 'object' || credential === null) return;
56
+ const projectId = nonEmptyString((credential as WithProjectId)[CREDENTIAL_PROJECT_ID]);
57
+ if (projectId !== undefined) defineHidden(app, APP_CREDENTIAL_PROJECT_ID, projectId);
58
+ }
59
+
60
+ /** firebase-admin's `getExplicitProjectId` for a sandbox admin app. */
61
+ export function explicitProjectId(app: { readonly options: { readonly projectId?: string } }): string | undefined {
62
+ return (
63
+ nonEmptyString(app.options.projectId) ??
64
+ nonEmptyString((app as WithProjectId)[APP_CREDENTIAL_PROJECT_ID]) ??
65
+ nonEmptyString(process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT)
66
+ );
67
+ }
@@ -0,0 +1,10 @@
1
+ import { PrefixedFirebaseError } from '../app/firebase-error.js';
2
+
3
+ export type AppCheckErrorCode = 'invalid-argument' | 'invalid-credential' | 'app-check-token-expired' | 'unknown-error';
4
+
5
+ /** firebase-admin's FirebaseAppCheckError: a PrefixedFirebaseError with prefix `app-check`. */
6
+ export class FirebaseAppCheckError extends PrefixedFirebaseError {
7
+ constructor(code: AppCheckErrorCode, message: string) {
8
+ super('app-check', code, message);
9
+ }
10
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * App Check tokens from Firebase: a token whose `kid` names a key that is not
3
+ * the sandbox's (#1552, #1301).
4
+ *
5
+ * In production AI mode the page's `firebase/app-check` is the Firebase SDK,
6
+ * so its tokens come from Firebase, and only firebase-admin's own verifier can
7
+ * check them. `@pyric/cli/register` installs that verifier behind
8
+ * {@link FIREBASE_VERIFIER} in production AI mode only, the same kind of seam
9
+ * as its `pyric.remote.sandboxFactory`: this package never learns what an AI
10
+ * mode is, and never loads firebase-admin itself.
11
+ *
12
+ * With no verifier installed the token is refused with a message that says
13
+ * why. The code stays `invalid-argument`, so a server that branches on it
14
+ * still answers 401.
15
+ */
16
+ import { FirebaseAppCheckError } from './error.js';
17
+ import type { VerifyAppCheckTokenResponse } from './index.js';
18
+
19
+ const FIREBASE_VERIFIER = Symbol.for('pyric.admin.appCheck.firebaseVerifier');
20
+
21
+ /** firebase-admin's `getAppCheck(app).verifyToken(token)` for an app scoped to `projectId`, with no options. */
22
+ type FirebaseVerifier = (token: string, projectId: string) => Promise<VerifyAppCheckTokenResponse>;
23
+
24
+ const MESSAGES = {
25
+ notSandbox:
26
+ "This App Check token was not minted by the Pyric sandbox, so the sandbox's firebase-admin/app-check cannot verify it. " +
27
+ 'A page in production AI mode gets its App Check tokens from Firebase. Start this server in production AI mode too ' +
28
+ '(PYRIC_AI_MODE=production) and Pyric verifies them with firebase-admin. In sandbox AI mode, page tokens come from the sandbox and verify here.',
29
+ install:
30
+ 'Production AI mode verifies App Check tokens from Firebase with firebase-admin, which is not installed beside this server. ' +
31
+ 'Install it in the project that runs the server (npm install firebase-admin) and restart.',
32
+ };
33
+
34
+ function installedVerifier(): FirebaseVerifier | undefined {
35
+ const verifier = (globalThis as Record<symbol, unknown>)[FIREBASE_VERIFIER];
36
+ return typeof verifier === 'function' ? (verifier as FirebaseVerifier) : undefined;
37
+ }
38
+
39
+ /** Whether a failure is the `firebase-admin` package itself not resolving, from ESM or CJS. */
40
+ function isFirebaseAdminMissing(error: unknown): boolean {
41
+ const { code, message } = (error ?? {}) as { code?: unknown; message?: unknown };
42
+ const isNotFound = code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND';
43
+ const namesFirebaseAdmin = typeof message === 'string' && /'firebase-admin[/']/.test(message);
44
+ return isNotFound && namesFirebaseAdmin;
45
+ }
46
+
47
+ /**
48
+ * Verifies a token from Firebase with firebase-admin, through the verifier the
49
+ * register installs. Its result and its errors come back unchanged.
50
+ */
51
+ export async function verifyFirebaseToken(token: string, projectId: string): Promise<VerifyAppCheckTokenResponse> {
52
+ const verifier = installedVerifier();
53
+ if (verifier === undefined) throw new FirebaseAppCheckError('invalid-argument', MESSAGES.notSandbox);
54
+ try {
55
+ return await verifier(token, projectId);
56
+ } catch (error) {
57
+ if (isFirebaseAdminMissing(error)) throw new FirebaseAppCheckError('invalid-argument', MESSAGES.install);
58
+ throw error;
59
+ }
60
+ }
@@ -10,11 +10,18 @@
10
10
  * One deliberate difference: the sandbox has no list of the project's
11
11
  * registered apps, so `createToken` accepts any app id (row
12
12
  * `app-check-admin#create-token-unknown-app`, diverged by design).
13
+ *
14
+ * A token whose `kid` is not the sandbox's came from Firebase. It goes to
15
+ * firebase-admin's own verifier when `@pyric/cli/register` installed one
16
+ * (production AI mode), and is refused with a message that says why otherwise
17
+ * (./firebase-token.ts).
13
18
  */
14
19
  import { checkAppCheckToken, mintAppCheckToken, type AppCheckTokenClaims } from 'pyric/sandbox/internal';
15
- import { PrefixedFirebaseError } from '../app/firebase-error.js';
16
20
  import { getApp, type PyricAdminApp } from '../app/index.js';
21
+ import { explicitProjectId } from '../app/project-id.js';
17
22
  import { assertAdminAppActive } from '../app/lifecycle.js';
23
+ import { FirebaseAppCheckError } from './error.js';
24
+ import { verifyFirebaseToken } from './firebase-token.js';
18
25
 
19
26
  const MINUTE_MILLIS = 60 * 1000;
20
27
  const MIN_TTL_MILLIS = 30 * MINUTE_MILLIS;
@@ -27,8 +34,6 @@ const MESSAGES = {
27
34
  algorithm: (alg: unknown) => `The provided App Check token has incorrect algorithm. Expected "RS256" but got "${String(alg)}".`,
28
35
  noSub: 'The provided App Check token has no "sub" (subject) claim.',
29
36
  emptySub: 'The provided App Check token has an empty string "sub" (subject) claim.',
30
- noMatchingKid:
31
- 'The provided App Check token has "kid" claim which does not correspond to a known public key. Most likely the provided App Check token is expired, so get a fresh token from your client app and try again.',
32
37
  ttl: 'ttlMillis must be a duration in milliseconds between 30 minutes and 7 days (inclusive).',
33
38
  appId: '`appId` must be a non-empty string.',
34
39
  decode: 'Decoding App Check token failed. Make sure you passed the entire string JWT which represents the Firebase App Check token.',
@@ -45,15 +50,6 @@ const MESSAGES = {
45
50
 
46
51
  const APP_CHECK_ISSUER = 'https://firebaseappcheck.googleapis.com/';
47
52
 
48
- type AppCheckErrorCode = 'invalid-argument' | 'invalid-credential' | 'app-check-token-expired' | 'unknown-error';
49
-
50
- /** firebase-admin's FirebaseAppCheckError: a PrefixedFirebaseError with prefix `app-check`. */
51
- class FirebaseAppCheckError extends PrefixedFirebaseError {
52
- constructor(code: AppCheckErrorCode, message: string) {
53
- super('app-check', code, message);
54
- }
55
- }
56
-
57
53
  export interface AppCheckTokenOptions {
58
54
  ttlMillis?: number;
59
55
  }
@@ -123,7 +119,7 @@ export class AppCheck {
123
119
  assertAdminAppActive(this.#app);
124
120
  if (typeof appId !== 'string' || appId.length === 0) throw new FirebaseAppCheckError('invalid-argument', MESSAGES.appId);
125
121
  const ttlMillis = ttlFrom(options);
126
- const projectId = this.#configuredProjectId();
122
+ const projectId = explicitProjectId(this.#app);
127
123
  if (!projectId) throw new FirebaseAppCheckError('unknown-error', MESSAGES.createNoProject);
128
124
  const minted = await mintAppCheckToken({ appId, projectId }, Math.floor(ttlMillis / 1000));
129
125
  return { token: minted.token, ttlMillis };
@@ -147,30 +143,44 @@ export class AppCheck {
147
143
  const projectId = this.#projectId();
148
144
  const check = await checkAppCheckToken(appCheckToken);
149
145
  if (!check.ok && check.reason === 'malformed') throw new FirebaseAppCheckError('invalid-argument', MESSAGES.decode);
146
+ // A kid that names a key other than the sandbox's: the token came from
147
+ // Firebase, so firebase-admin runs every check, in production's order.
148
+ const isFirebaseToken = !check.ok && check.reason === 'kid';
149
+ if (isFirebaseToken) {
150
+ const verified = await verifyFirebaseToken(appCheckToken, projectId);
151
+ return this.#recordConsume(verified, appCheckToken, options);
152
+ }
150
153
  verifyContent(check.header, check.claims, projectId);
151
- if (!check.ok && check.reason === 'kid') throw new FirebaseAppCheckError('invalid-argument', MESSAGES.noMatchingKid);
152
154
  if (!check.ok) throw new FirebaseAppCheckError('invalid-argument', MESSAGES.signature);
153
155
  verifyNotBefore(check.claims.nbf);
154
156
  verifyExpiry(check.claims.exp);
155
157
  const claims = check.claims as AppCheckTokenClaims;
156
158
  const result: VerifyAppCheckTokenResponse = { appId: claims.sub, token: { ...claims, app_id: claims.sub } };
157
- if (options?.consume) {
158
- const consumed = consumedFor(this.#app);
159
- const tokenId = typeof claims.jti === 'string' ? claims.jti : appCheckToken;
160
- result.alreadyConsumed = consumed.has(tokenId);
161
- consumed.add(tokenId);
162
- }
163
- return result;
159
+ return this.#recordConsume(result, appCheckToken, options);
164
160
  }
165
161
 
166
- /** The app's project, found where firebase-admin's findProjectId looks: the app options, then the environment. */
167
- #configuredProjectId(): string | undefined {
168
- return this.#app.options.projectId || process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT || undefined;
162
+ /**
163
+ * `consume: true` marks the token used, in this process, for sandbox and
164
+ * Firebase tokens alike. It is never forwarded to Firebase, which would need
165
+ * a credential with App Check permissions.
166
+ */
167
+ #recordConsume(
168
+ result: VerifyAppCheckTokenResponse,
169
+ appCheckToken: string,
170
+ options: VerifyAppCheckTokenOptions | undefined,
171
+ ): VerifyAppCheckTokenResponse {
172
+ if (!options?.consume) return result;
173
+ const consumed = consumedFor(this.#app);
174
+ const jti = result.token.jti;
175
+ const tokenId = typeof jti === 'string' ? jti : appCheckToken;
176
+ result.alreadyConsumed = consumed.has(tokenId);
177
+ consumed.add(tokenId);
178
+ return result;
169
179
  }
170
180
 
171
181
  /** The project a token must be scoped to, resolved as firebase-admin resolves it. */
172
182
  #projectId(): string {
173
- const projectId = this.#configuredProjectId();
183
+ const projectId = explicitProjectId(this.#app);
174
184
  if (!projectId) throw new FirebaseAppCheckError('invalid-credential', MESSAGES.noProject);
175
185
  return projectId;
176
186
  }