pyric 0.1.0-alpha.29 → 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.
- package/dist/app-check/errors.d.ts +14 -0
- package/dist/app-check/errors.d.ts.map +1 -0
- package/dist/app-check/errors.js +15 -0
- package/dist/app-check/errors.js.map +1 -0
- package/dist/app-check/index.d.ts +25 -30
- package/dist/app-check/index.d.ts.map +1 -1
- package/dist/app-check/index.js +62 -15
- package/dist/app-check/index.js.map +1 -1
- package/dist/app-check/providers.d.ts +36 -0
- package/dist/app-check/providers.d.ts.map +1 -0
- package/dist/app-check/providers.js +32 -0
- package/dist/app-check/providers.js.map +1 -0
- package/dist/app-check/state.d.ts +29 -0
- package/dist/app-check/state.d.ts.map +1 -0
- package/dist/app-check/state.js +47 -0
- package/dist/app-check/state.js.map +1 -0
- package/dist/deferred/entry.d.ts +1 -1
- package/dist/deferred/entry.js +1 -1
- package/dist/sandbox/internal/app-check-token.d.ts +46 -0
- package/dist/sandbox/internal/app-check-token.d.ts.map +1 -0
- package/dist/sandbox/internal/app-check-token.js +125 -0
- package/dist/sandbox/internal/app-check-token.js.map +1 -0
- package/dist/sandbox/internal/index.d.ts +1 -0
- package/dist/sandbox/internal/index.d.ts.map +1 -1
- package/dist/sandbox/internal/index.js +1 -0
- package/dist/sandbox/internal/index.js.map +1 -1
- package/package.json +1 -1
- package/src/app-check/errors.ts +20 -0
- package/src/app-check/index.ts +106 -37
- package/src/app-check/providers.ts +46 -0
- package/src/app-check/state.ts +79 -0
- package/src/deferred/entry.ts +1 -1
- package/src/sandbox/internal/app-check-token.ts +165 -0
- package/src/sandbox/internal/index.ts +11 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App Check errors with the codes, messages, and customData production
|
|
3
|
+
* throws (captures `app-check-client-initialize-twice` and
|
|
4
|
+
* `app-check-client-get-token-before-initialize`).
|
|
5
|
+
*/
|
|
6
|
+
import { FirebaseError } from '../sandbox/internal/firebase-error.js';
|
|
7
|
+
declare const MESSAGES: {
|
|
8
|
+
readonly 'already-initialized': (appName: string) => string;
|
|
9
|
+
readonly 'use-before-activation': (appName: string) => string;
|
|
10
|
+
};
|
|
11
|
+
export type AppCheckErrorCode = keyof typeof MESSAGES;
|
|
12
|
+
export declare function appCheckError(code: AppCheckErrorCode, appName: string): FirebaseError;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/app-check/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAEtE,QAAA,MAAM,QAAQ;8CACqB,MAAM;gDAEJ,MAAM;CAEjC,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,QAAQ,CAAC;AAEtD,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAGrF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App Check errors with the codes, messages, and customData production
|
|
3
|
+
* throws (captures `app-check-client-initialize-twice` and
|
|
4
|
+
* `app-check-client-get-token-before-initialize`).
|
|
5
|
+
*/
|
|
6
|
+
import { FirebaseError } from '../sandbox/internal/firebase-error.js';
|
|
7
|
+
const MESSAGES = {
|
|
8
|
+
'already-initialized': (appName) => `You have already called initializeAppCheck() for FirebaseApp ${appName} with different options. To avoid this error, call initializeAppCheck() with the same options as when it was originally called. This will return the already initialized instance.`,
|
|
9
|
+
'use-before-activation': (appName) => `App Check is being used before initializeAppCheck() is called for FirebaseApp ${appName}. Call initializeAppCheck() before instantiating other Firebase services.`,
|
|
10
|
+
};
|
|
11
|
+
export function appCheckError(code, appName) {
|
|
12
|
+
const fullCode = `appCheck/${code}`;
|
|
13
|
+
return new FirebaseError(fullCode, `AppCheck: ${MESSAGES[code](appName)} (${fullCode}).`, { appName });
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/app-check/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAEtE,MAAM,QAAQ,GAAG;IACf,qBAAqB,EAAE,CAAC,OAAe,EAAE,EAAE,CACzC,gEAAgE,OAAO,oLAAoL;IAC7P,uBAAuB,EAAE,CAAC,OAAe,EAAE,EAAE,CAC3C,iFAAiF,OAAO,2EAA2E;CAC7J,CAAC;AAIX,MAAM,UAAU,aAAa,CAAC,IAAuB,EAAE,OAAe;IACpE,MAAM,QAAQ,GAAG,YAAY,IAAI,EAAE,CAAC;IACpC,OAAO,IAAI,aAAa,CAAC,QAAQ,EAAE,aAAa,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AACzG,CAAC"}
|
|
@@ -1,31 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export
|
|
22
|
-
export
|
|
23
|
-
export
|
|
24
|
-
export
|
|
25
|
-
export
|
|
26
|
-
export type CustomProviderOptions = DeferredApi;
|
|
27
|
-
export type PartialObserver = DeferredApi;
|
|
28
|
-
export type ReCaptchaEnterpriseProvider = DeferredApi;
|
|
29
|
-
export type ReCaptchaV3Provider = DeferredApi;
|
|
30
|
-
export type Unsubscribe = DeferredApi;
|
|
1
|
+
import type { FirebaseApp } from '../app/types.js';
|
|
2
|
+
import { CustomProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider, type AppCheckProvider } from './providers.js';
|
|
3
|
+
import { type AppCheckTokenResult } from './state.js';
|
|
4
|
+
export { CustomProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider };
|
|
5
|
+
export type { CustomProviderOptions, AppCheckTokenFromProvider as AppCheckToken } from './providers.js';
|
|
6
|
+
export type { AppCheckTokenResult } from './state.js';
|
|
7
|
+
export interface AppCheck {
|
|
8
|
+
readonly app: FirebaseApp;
|
|
9
|
+
}
|
|
10
|
+
export interface AppCheckOptions {
|
|
11
|
+
provider: AppCheckProvider;
|
|
12
|
+
isTokenAutoRefreshEnabled?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export type AppCheckTokenListener = (token: AppCheckTokenResult) => void;
|
|
15
|
+
export type Unsubscribe = () => void;
|
|
16
|
+
export interface PartialObserver<T> {
|
|
17
|
+
next?: (value: T) => void;
|
|
18
|
+
error?: (error: Error) => void;
|
|
19
|
+
complete?: () => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function initializeAppCheck(app: FirebaseApp | undefined, options: AppCheckOptions): AppCheck;
|
|
22
|
+
export declare function getToken(appCheck: AppCheck, forceRefresh?: boolean): Promise<AppCheckTokenResult>;
|
|
23
|
+
export declare function getLimitedUseToken(appCheck: AppCheck): Promise<AppCheckTokenResult>;
|
|
24
|
+
export declare function setTokenAutoRefreshEnabled(appCheck: AppCheck, isTokenAutoRefreshEnabled: boolean): void;
|
|
25
|
+
export declare function onTokenChanged(appCheck: AppCheck, onNextOrObserver: AppCheckTokenListener | PartialObserver<AppCheckTokenResult>, onError?: (error: Error) => void, onCompletion?: () => void): Unsubscribe;
|
|
31
26
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/app-check/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/app-check/index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,2BAA2B,EAAE,mBAAmB,EAAgB,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvI,OAAO,EAOL,KAAK,mBAAmB,EAEzB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,CAAC;AAC5E,YAAY,EAAE,qBAAqB,EAAE,yBAAyB,IAAI,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACxG,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;AACzE,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AACrC,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAaD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,GAAG,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,QAAQ,CAWnG;AAQD,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,UAAQ,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAGrG;AAED,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAGzF;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,QAAQ,EAAE,yBAAyB,EAAE,OAAO,GAAG,IAAI,CAEvG;AAaD,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,QAAQ,EAClB,gBAAgB,EAAE,qBAAqB,GAAG,eAAe,CAAC,mBAAmB,CAAC,EAC9E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,EAChC,YAAY,CAAC,EAAE,MAAM,IAAI,GACxB,WAAW,CAEb"}
|
package/dist/app-check/index.js
CHANGED
|
@@ -1,20 +1,67 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `pyric/app-check
|
|
2
|
+
* `pyric/app-check`: the sandbox mirror of `firebase/app-check`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The sandbox has no attestation authority, so it behaves like production
|
|
5
|
+
* under a registered debug token: providers are accepted and never called,
|
|
6
|
+
* and every token request succeeds with a token of production's shape. The
|
|
7
|
+
* conformance rows are in packages/conformance/registry/app-check.ts and the
|
|
8
|
+
* suite in packages/pyric/test/app-check/oracle-conformance.test.ts.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
* `pyric` still loads; touching one throws `PyricDeferredApiError` naming this
|
|
11
|
-
* subpath. See `../deferred/entry.ts` for the full rationale.
|
|
12
|
-
*
|
|
13
|
-
* The value list is the exact public runtime surface of `firebase/app-check`
|
|
14
|
-
* (Firebase Web SDK 12.13.0). Keep it in sync when this entry graduates to a
|
|
15
|
-
* real mirror.
|
|
10
|
+
* The value surface is exactly `firebase/app-check` 12.13.0's.
|
|
16
11
|
*/
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
import { getApp } from '../app/registry.js';
|
|
13
|
+
import { appCheckError } from './errors.js';
|
|
14
|
+
import { CustomProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider, sameProvider } from './providers.js';
|
|
15
|
+
import { activate, addObserver, cachedOrMint, mintLimitedUse, stateOf, } from './state.js';
|
|
16
|
+
export { CustomProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider };
|
|
17
|
+
class AppCheckHandle {
|
|
18
|
+
app;
|
|
19
|
+
constructor(app) {
|
|
20
|
+
this.app = app;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const handles = new WeakMap();
|
|
24
|
+
function hasSameOptions(state, options) {
|
|
25
|
+
const refresh = options.isTokenAutoRefreshEnabled ?? false;
|
|
26
|
+
return state.initialAutoRefresh === refresh && sameProvider(state.provider, options.provider);
|
|
27
|
+
}
|
|
28
|
+
export function initializeAppCheck(app, options) {
|
|
29
|
+
const target = app ?? getApp();
|
|
30
|
+
const existing = stateOf(target);
|
|
31
|
+
if (existing) {
|
|
32
|
+
if (!hasSameOptions(existing, options))
|
|
33
|
+
throw appCheckError('already-initialized', target.name);
|
|
34
|
+
return handles.get(target);
|
|
35
|
+
}
|
|
36
|
+
activate(target, options.provider, options.isTokenAutoRefreshEnabled ?? false);
|
|
37
|
+
const handle = new AppCheckHandle(target);
|
|
38
|
+
handles.set(target, handle);
|
|
39
|
+
return handle;
|
|
40
|
+
}
|
|
41
|
+
function activeState(appCheck) {
|
|
42
|
+
const state = stateOf(appCheck.app);
|
|
43
|
+
if (!state)
|
|
44
|
+
throw appCheckError('use-before-activation', appCheck.app.name);
|
|
45
|
+
return state;
|
|
46
|
+
}
|
|
47
|
+
export async function getToken(appCheck, forceRefresh = false) {
|
|
48
|
+
const state = activeState(appCheck);
|
|
49
|
+
return cachedOrMint(appCheck.app, state, forceRefresh);
|
|
50
|
+
}
|
|
51
|
+
export async function getLimitedUseToken(appCheck) {
|
|
52
|
+
activeState(appCheck);
|
|
53
|
+
return mintLimitedUse(appCheck.app);
|
|
54
|
+
}
|
|
55
|
+
export function setTokenAutoRefreshEnabled(appCheck, isTokenAutoRefreshEnabled) {
|
|
56
|
+
activeState(appCheck).isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled;
|
|
57
|
+
}
|
|
58
|
+
function toObserver(onNextOrObserver, onError, onCompletion) {
|
|
59
|
+
if (typeof onNextOrObserver === 'function') {
|
|
60
|
+
return { next: onNextOrObserver, error: onError, complete: onCompletion };
|
|
61
|
+
}
|
|
62
|
+
return { next: onNextOrObserver.next ?? (() => { }), error: onNextOrObserver.error, complete: onNextOrObserver.complete };
|
|
63
|
+
}
|
|
64
|
+
export function onTokenChanged(appCheck, onNextOrObserver, onError, onCompletion) {
|
|
65
|
+
return addObserver(activeState(appCheck), toObserver(onNextOrObserver, onError, onCompletion));
|
|
66
|
+
}
|
|
20
67
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/app-check/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/app-check/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The three attestation providers. The sandbox has no attestation service, so
|
|
3
|
+
* it never calls a provider, as production never does under a debug token
|
|
4
|
+
* (capture `app-check-client-debug-get-token`, `customProviderCalls: 0`).
|
|
5
|
+
* `isEqual` decides whether a second `initializeAppCheck` has the same options.
|
|
6
|
+
*/
|
|
7
|
+
export interface AppCheckTokenFromProvider {
|
|
8
|
+
readonly token: string;
|
|
9
|
+
readonly expireTimeMillis: number;
|
|
10
|
+
}
|
|
11
|
+
export interface CustomProviderOptions {
|
|
12
|
+
getToken: () => Promise<AppCheckTokenFromProvider>;
|
|
13
|
+
}
|
|
14
|
+
interface ComparableProvider {
|
|
15
|
+
isEqual(other: unknown): boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare class ReCaptchaV3Provider implements ComparableProvider {
|
|
18
|
+
private readonly siteKey;
|
|
19
|
+
constructor(siteKey: string);
|
|
20
|
+
isEqual(other: unknown): boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare class ReCaptchaEnterpriseProvider implements ComparableProvider {
|
|
23
|
+
private readonly siteKey;
|
|
24
|
+
constructor(siteKey: string);
|
|
25
|
+
isEqual(other: unknown): boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare class CustomProvider implements ComparableProvider {
|
|
28
|
+
private readonly options;
|
|
29
|
+
constructor(options: CustomProviderOptions);
|
|
30
|
+
/** Upstream compares the getToken functions by source text, so a provider rebuilt by the same factory is equal. */
|
|
31
|
+
isEqual(other: unknown): boolean;
|
|
32
|
+
}
|
|
33
|
+
export type AppCheckProvider = ReCaptchaV3Provider | ReCaptchaEnterpriseProvider | CustomProvider;
|
|
34
|
+
export declare function sameProvider(a: AppCheckProvider, b: AppCheckProvider): boolean;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/app-check/providers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,CAAC;CACpD;AAED,UAAU,kBAAkB;IAC1B,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;CAClC;AAED,qBAAa,mBAAoB,YAAW,kBAAkB;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,MAAM;IAC5C,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;CAGjC;AAED,qBAAa,2BAA4B,YAAW,kBAAkB;IACxD,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,MAAM;IAC5C,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;CAGjC;AAED,qBAAa,cAAe,YAAW,kBAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,qBAAqB;IAC3D,mHAAmH;IACnH,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;CAGjC;AAED,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,GAAG,2BAA2B,GAAG,cAAc,CAAC;AAElG,wBAAgB,YAAY,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAE9E"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export class ReCaptchaV3Provider {
|
|
2
|
+
siteKey;
|
|
3
|
+
constructor(siteKey) {
|
|
4
|
+
this.siteKey = siteKey;
|
|
5
|
+
}
|
|
6
|
+
isEqual(other) {
|
|
7
|
+
return other instanceof ReCaptchaV3Provider && other.siteKey === this.siteKey;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class ReCaptchaEnterpriseProvider {
|
|
11
|
+
siteKey;
|
|
12
|
+
constructor(siteKey) {
|
|
13
|
+
this.siteKey = siteKey;
|
|
14
|
+
}
|
|
15
|
+
isEqual(other) {
|
|
16
|
+
return other instanceof ReCaptchaEnterpriseProvider && other.siteKey === this.siteKey;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class CustomProvider {
|
|
20
|
+
options;
|
|
21
|
+
constructor(options) {
|
|
22
|
+
this.options = options;
|
|
23
|
+
}
|
|
24
|
+
/** Upstream compares the getToken functions by source text, so a provider rebuilt by the same factory is equal. */
|
|
25
|
+
isEqual(other) {
|
|
26
|
+
return other instanceof CustomProvider && String(other.options.getToken) === String(this.options.getToken);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function sameProvider(a, b) {
|
|
30
|
+
return a.isEqual(b);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/app-check/providers.ts"],"names":[],"mappings":"AAmBA,MAAM,OAAO,mBAAmB;IACD;IAA7B,YAA6B,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;IAAG,CAAC;IAChD,OAAO,CAAC,KAAc;QACpB,OAAO,KAAK,YAAY,mBAAmB,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC;IAChF,CAAC;CACF;AAED,MAAM,OAAO,2BAA2B;IACT;IAA7B,YAA6B,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;IAAG,CAAC;IAChD,OAAO,CAAC,KAAc;QACpB,OAAO,KAAK,YAAY,2BAA2B,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC;IACxF,CAAC;CACF;AAED,MAAM,OAAO,cAAc;IACI;IAA7B,YAA6B,OAA8B;QAA9B,YAAO,GAAP,OAAO,CAAuB;IAAG,CAAC;IAC/D,mHAAmH;IACnH,OAAO,CAAC,KAAc;QACpB,OAAO,KAAK,YAAY,cAAc,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7G,CAAC;CACF;AAID,MAAM,UAAU,YAAY,CAAC,CAAmB,EAAE,CAAmB;IACnE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-app App Check state: the activation options, the cached token, and the
|
|
3
|
+
* token listeners. Keyed by the app object, as upstream keys it.
|
|
4
|
+
*/
|
|
5
|
+
import type { FirebaseApp } from '../app/types.js';
|
|
6
|
+
import { type MintedAppCheckToken as MintedToken } from '../sandbox/internal/app-check-token.js';
|
|
7
|
+
import type { AppCheckProvider } from './providers.js';
|
|
8
|
+
export interface AppCheckTokenResult {
|
|
9
|
+
readonly token: string;
|
|
10
|
+
}
|
|
11
|
+
export interface TokenObserver {
|
|
12
|
+
next: (result: AppCheckTokenResult) => void;
|
|
13
|
+
error?: (error: Error) => void;
|
|
14
|
+
complete?: () => void;
|
|
15
|
+
}
|
|
16
|
+
export interface AppCheckState {
|
|
17
|
+
provider: AppCheckProvider;
|
|
18
|
+
/** The option `initializeAppCheck` was called with; a later call is compared with this. */
|
|
19
|
+
readonly initialAutoRefresh: boolean;
|
|
20
|
+
isTokenAutoRefreshEnabled: boolean;
|
|
21
|
+
cached: MintedToken | null;
|
|
22
|
+
observers: Set<TokenObserver>;
|
|
23
|
+
}
|
|
24
|
+
export declare function stateOf(app: FirebaseApp): AppCheckState | undefined;
|
|
25
|
+
export declare function activate(app: FirebaseApp, provider: AppCheckProvider, isTokenAutoRefreshEnabled: boolean): AppCheckState;
|
|
26
|
+
export declare function cachedOrMint(app: FirebaseApp, state: AppCheckState, forceRefresh: boolean): Promise<AppCheckTokenResult>;
|
|
27
|
+
export declare function mintLimitedUse(app: FirebaseApp): Promise<AppCheckTokenResult>;
|
|
28
|
+
export declare function addObserver(state: AppCheckState, observer: TokenObserver): () => void;
|
|
29
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/app-check/state.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAqB,KAAK,mBAAmB,IAAI,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAIpH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,2FAA2F;IAC3F,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,yBAAyB,EAAE,OAAO,CAAC;IACnC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;CAC/B;AAID,wBAAgB,OAAO,CAAC,GAAG,EAAE,WAAW,GAAG,aAAa,GAAG,SAAS,CAEnE;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,OAAO,GAAG,aAAa,CAIxH;AAkBD,wBAAsB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAQ9H;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAEnF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,GAAG,MAAM,IAAI,CAMrF"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { mintAppCheckToken } from '../sandbox/internal/app-check-token.js';
|
|
2
|
+
/** Web App Check tokens live one hour (capture `app-check-client-debug-get-token`). */
|
|
3
|
+
const TTL_SECONDS = 3600;
|
|
4
|
+
const states = new WeakMap();
|
|
5
|
+
export function stateOf(app) {
|
|
6
|
+
return states.get(app);
|
|
7
|
+
}
|
|
8
|
+
export function activate(app, provider, isTokenAutoRefreshEnabled) {
|
|
9
|
+
const state = { provider, initialAutoRefresh: isTokenAutoRefreshEnabled, isTokenAutoRefreshEnabled, cached: null, observers: new Set() };
|
|
10
|
+
states.set(app, state);
|
|
11
|
+
return state;
|
|
12
|
+
}
|
|
13
|
+
function identityOf(app) {
|
|
14
|
+
const options = app.options;
|
|
15
|
+
return { appId: options.appId ?? '', projectId: options.projectId ?? '' };
|
|
16
|
+
}
|
|
17
|
+
/** Delivers a token to observers off the caller's stack, as the SDK does. */
|
|
18
|
+
function notify(observers, result) {
|
|
19
|
+
for (const observer of observers) {
|
|
20
|
+
queueMicrotask(() => observer.next(result));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function isValid(token, nowMillis) {
|
|
24
|
+
return token !== null && token.expireTimeMillis > nowMillis;
|
|
25
|
+
}
|
|
26
|
+
export async function cachedOrMint(app, state, forceRefresh) {
|
|
27
|
+
const now = Date.now();
|
|
28
|
+
const reuse = !forceRefresh && isValid(state.cached, now);
|
|
29
|
+
if (reuse)
|
|
30
|
+
return { token: state.cached.token };
|
|
31
|
+
state.cached = await mintAppCheckToken(identityOf(app), TTL_SECONDS, now);
|
|
32
|
+
const result = { token: state.cached.token };
|
|
33
|
+
notify(state.observers, result);
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
export async function mintLimitedUse(app) {
|
|
37
|
+
return { token: (await mintAppCheckToken(identityOf(app), TTL_SECONDS)).token };
|
|
38
|
+
}
|
|
39
|
+
export function addObserver(state, observer) {
|
|
40
|
+
state.observers.add(observer);
|
|
41
|
+
if (isValid(state.cached, Date.now()))
|
|
42
|
+
notify([observer], { token: state.cached.token });
|
|
43
|
+
return () => {
|
|
44
|
+
state.observers.delete(observer);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/app-check/state.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAA2C,MAAM,wCAAwC,CAAC;AAEpH,uFAAuF;AACvF,MAAM,WAAW,GAAG,IAAI,CAAC;AAsBzB,MAAM,MAAM,GAAG,IAAI,OAAO,EAA8B,CAAC;AAEzD,MAAM,UAAU,OAAO,CAAC,GAAgB;IACtC,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAgB,EAAE,QAA0B,EAAE,yBAAkC;IACvG,MAAM,KAAK,GAAkB,EAAE,QAAQ,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IACxJ,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CAAC,GAAgB;IAClC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAiD,CAAC;IACtE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;AAC5E,CAAC;AAED,6EAA6E;AAC7E,SAAS,MAAM,CAAC,SAAkC,EAAE,MAA2B;IAC7E,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,cAAc,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CAAC,KAAyB,EAAE,SAAiB;IAC3D,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,gBAAgB,GAAG,SAAS,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAgB,EAAE,KAAoB,EAAE,YAAqB;IAC9F,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1D,IAAI,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,MAAO,CAAC,KAAK,EAAE,CAAC;IACjD,KAAK,CAAC,MAAM,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAgB;IACnD,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,iBAAiB,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAoB,EAAE,QAAuB;IACvE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9B,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;QAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACzF,OAAO,GAAG,EAAE;QACV,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/deferred/entry.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The shared factory behind pyric's *deferred* Firebase Web SDK subpaths —
|
|
3
|
-
* `pyric/functions`, `pyric/analytics`,
|
|
3
|
+
* `pyric/functions`, `pyric/analytics`,
|
|
4
4
|
* `pyric/firestore/lite`, `pyric/performance` and `pyric/remote-config`.
|
|
5
5
|
*
|
|
6
6
|
* WHY THESE EXIST AT ALL. pyric is a symbol-for-symbol drop-in for the
|
package/dist/deferred/entry.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The shared factory behind pyric's *deferred* Firebase Web SDK subpaths —
|
|
3
|
-
* `pyric/functions`, `pyric/analytics`,
|
|
3
|
+
* `pyric/functions`, `pyric/analytics`,
|
|
4
4
|
* `pyric/firestore/lite`, `pyric/performance` and `pyric/remote-config`.
|
|
5
5
|
*
|
|
6
6
|
* WHY THESE EXIST AT ALL. pyric is a symbol-for-symbol drop-in for the
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface AppCheckIdentity {
|
|
2
|
+
appId: string;
|
|
3
|
+
projectId: string;
|
|
4
|
+
}
|
|
5
|
+
export interface AppCheckTokenClaims {
|
|
6
|
+
sub: string;
|
|
7
|
+
aud: string[];
|
|
8
|
+
provider: string;
|
|
9
|
+
iss: string;
|
|
10
|
+
exp: number;
|
|
11
|
+
iat: number;
|
|
12
|
+
jti: string;
|
|
13
|
+
[claim: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
export interface MintedAppCheckToken {
|
|
16
|
+
token: string;
|
|
17
|
+
expireTimeMillis: number;
|
|
18
|
+
}
|
|
19
|
+
/** The project number a Firebase app id carries: `1:<projectNumber>:<platform>:<hash>`. */
|
|
20
|
+
export declare function appCheckProjectNumber(appId: string): string;
|
|
21
|
+
export declare function mintAppCheckToken(identity: AppCheckIdentity, ttlSeconds: number, nowMillis?: number): Promise<MintedAppCheckToken>;
|
|
22
|
+
/** Signs any header and claims with the sandbox key. Minting uses it; tests use it to build tokens production could not issue. */
|
|
23
|
+
export declare function signAppCheckToken(header: Record<string, unknown>, claims: Record<string, unknown>): Promise<string>;
|
|
24
|
+
/** A decoded token's header and claims, unchecked: any field may be missing or of any type. */
|
|
25
|
+
export interface AppCheckTokenParts {
|
|
26
|
+
header: Readonly<Record<string, unknown>>;
|
|
27
|
+
claims: Readonly<Record<string, unknown>>;
|
|
28
|
+
}
|
|
29
|
+
export type AppCheckTokenCheck = ({
|
|
30
|
+
ok: true;
|
|
31
|
+
} & AppCheckTokenParts) | ({
|
|
32
|
+
ok: false;
|
|
33
|
+
reason: 'kid' | 'signature';
|
|
34
|
+
} & AppCheckTokenParts) | {
|
|
35
|
+
ok: false;
|
|
36
|
+
reason: 'malformed';
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Decodes a sandbox token and checks its key and signature, in
|
|
40
|
+
* firebase-admin's order: a `kid` must name the sandbox key, and a token with
|
|
41
|
+
* no `kid` is checked against it, as firebase-admin tries every key. The
|
|
42
|
+
* decoded header and claims come back whenever the token decodes; `alg`,
|
|
43
|
+
* audience, subject and expiry are the caller's rules.
|
|
44
|
+
*/
|
|
45
|
+
export declare function checkAppCheckToken(token: string): Promise<AppCheckTokenCheck>;
|
|
46
|
+
//# sourceMappingURL=app-check-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-check-token.d.ts","sourceRoot":"","sources":["../../../src/sandbox/internal/app-check-token.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAuDD,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,gBAAgB,EAC1B,UAAU,EAAE,MAAM,EAClB,SAAS,GAAE,MAAmB,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CAe9B;AAED,kIAAkI;AAClI,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAGzH;AAED,+FAA+F;AAC/F,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1C,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC3C;AAED,MAAM,MAAM,kBAAkB,GAC1B,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,kBAAkB,CAAC,GACnC,CAAC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,KAAK,GAAG,WAAW,CAAA;CAAE,GAAG,kBAAkB,CAAC,GACjE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC;AAEvC;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmBnF"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandbox App Check tokens, shared by the web mirror (`pyric/app-check`) and
|
|
3
|
+
* the admin mirror (`pyric-admin/app-check`) so a token minted on either plane
|
|
4
|
+
* verifies on the other, as production's do (capture
|
|
5
|
+
* `app-check-admin-verify-token`, `debugExchanged`).
|
|
6
|
+
*
|
|
7
|
+
* Shape (captures `app-check-client-debug-get-token`,
|
|
8
|
+
* `app-check-admin-create-token-shape`): a three-segment JWT, header `alg`
|
|
9
|
+
* RS256, `typ` JWT, a `kid`; claims `aud`, `exp`, `iat`, `iss`, `jti`,
|
|
10
|
+
* `provider`, `sub`; `iss` and `aud` name the project number from the app id.
|
|
11
|
+
*
|
|
12
|
+
* The signature is not RSA. It is a 256-byte SHA-256 expansion over the
|
|
13
|
+
* signing input and a fixed sandbox key, the length of a real RS256
|
|
14
|
+
* signature, so any edit to the header, payload, or signature fails
|
|
15
|
+
* verification. It is not a security boundary: anyone can mint one.
|
|
16
|
+
*/
|
|
17
|
+
const ISSUER = 'https://firebaseappcheck.googleapis.com';
|
|
18
|
+
const SANDBOX_KID = 'pyric-sandbox';
|
|
19
|
+
const SANDBOX_KEY = 'pyric-sandbox-app-check-signing-key';
|
|
20
|
+
const SIGNATURE_BLOCKS = 8;
|
|
21
|
+
function base64url(bytes) {
|
|
22
|
+
let binary = '';
|
|
23
|
+
for (const byte of bytes)
|
|
24
|
+
binary += String.fromCharCode(byte);
|
|
25
|
+
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
26
|
+
}
|
|
27
|
+
/** jws `JWS_REGEX`: base64url characters only, header and payload non-empty, signature optional. */
|
|
28
|
+
const JWS_SHAPE = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;
|
|
29
|
+
/** A base64url segment as Latin-1 text, one character per byte, as jws reads a header (`toString('binary')`). */
|
|
30
|
+
function latin1FromBase64url(text) {
|
|
31
|
+
const padded = text.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(text.length / 4) * 4, '=');
|
|
32
|
+
return atob(padded);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A base64url segment as UTF-8, as jws reads a payload (`toString('utf8')`):
|
|
36
|
+
* the inverse of {@link encodeJson}, with invalid bytes replaced by U+FFFD as
|
|
37
|
+
* Buffer does. Uses `atob` and `TextDecoder` only, so it runs the same in a
|
|
38
|
+
* browser or worker.
|
|
39
|
+
*/
|
|
40
|
+
function utf8FromBase64url(text) {
|
|
41
|
+
const binary = latin1FromBase64url(text);
|
|
42
|
+
const bytes = new Uint8Array(binary.length);
|
|
43
|
+
for (let index = 0; index < binary.length; index++)
|
|
44
|
+
bytes[index] = binary.charCodeAt(index);
|
|
45
|
+
return new TextDecoder('utf-8').decode(bytes);
|
|
46
|
+
}
|
|
47
|
+
function isJsonObject(value) {
|
|
48
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
49
|
+
}
|
|
50
|
+
function encodeJson(value) {
|
|
51
|
+
return base64url(new TextEncoder().encode(JSON.stringify(value)));
|
|
52
|
+
}
|
|
53
|
+
function randomId() {
|
|
54
|
+
const bytes = new Uint8Array(32);
|
|
55
|
+
crypto.getRandomValues(bytes);
|
|
56
|
+
return base64url(bytes);
|
|
57
|
+
}
|
|
58
|
+
async function sandboxSignature(signingInput) {
|
|
59
|
+
const blocks = [];
|
|
60
|
+
for (let block = 0; block < SIGNATURE_BLOCKS; block++) {
|
|
61
|
+
const data = new TextEncoder().encode(`${block}.${SANDBOX_KEY}.${signingInput}`);
|
|
62
|
+
blocks.push(new Uint8Array(await crypto.subtle.digest('SHA-256', data)));
|
|
63
|
+
}
|
|
64
|
+
const out = new Uint8Array(blocks.length * 32);
|
|
65
|
+
blocks.forEach((bytes, index) => out.set(bytes, index * 32));
|
|
66
|
+
return base64url(out);
|
|
67
|
+
}
|
|
68
|
+
/** The project number a Firebase app id carries: `1:<projectNumber>:<platform>:<hash>`. */
|
|
69
|
+
export function appCheckProjectNumber(appId) {
|
|
70
|
+
return appId.split(':')[1] ?? '';
|
|
71
|
+
}
|
|
72
|
+
export async function mintAppCheckToken(identity, ttlSeconds, nowMillis = Date.now()) {
|
|
73
|
+
const iat = Math.floor(nowMillis / 1000);
|
|
74
|
+
const exp = iat + ttlSeconds;
|
|
75
|
+
const projectNumber = appCheckProjectNumber(identity.appId);
|
|
76
|
+
const claims = {
|
|
77
|
+
sub: identity.appId,
|
|
78
|
+
aud: [`projects/${projectNumber}`, `projects/${identity.projectId}`],
|
|
79
|
+
provider: 'pyric-sandbox',
|
|
80
|
+
iss: `${ISSUER}/${projectNumber}`,
|
|
81
|
+
exp,
|
|
82
|
+
iat,
|
|
83
|
+
jti: randomId(),
|
|
84
|
+
};
|
|
85
|
+
const token = await signAppCheckToken({ alg: 'RS256', kid: SANDBOX_KID, typ: 'JWT' }, claims);
|
|
86
|
+
return { token, expireTimeMillis: exp * 1000 };
|
|
87
|
+
}
|
|
88
|
+
/** Signs any header and claims with the sandbox key. Minting uses it; tests use it to build tokens production could not issue. */
|
|
89
|
+
export async function signAppCheckToken(header, claims) {
|
|
90
|
+
const signingInput = `${encodeJson(header)}.${encodeJson(claims)}`;
|
|
91
|
+
return `${signingInput}.${await sandboxSignature(signingInput)}`;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Decodes a sandbox token and checks its key and signature, in
|
|
95
|
+
* firebase-admin's order: a `kid` must name the sandbox key, and a token with
|
|
96
|
+
* no `kid` is checked against it, as firebase-admin tries every key. The
|
|
97
|
+
* decoded header and claims come back whenever the token decodes; `alg`,
|
|
98
|
+
* audience, subject and expiry are the caller's rules.
|
|
99
|
+
*/
|
|
100
|
+
export async function checkAppCheckToken(token) {
|
|
101
|
+
if (!JWS_SHAPE.test(token))
|
|
102
|
+
return { ok: false, reason: 'malformed' };
|
|
103
|
+
const segments = token.split('.');
|
|
104
|
+
let header;
|
|
105
|
+
let claims;
|
|
106
|
+
try {
|
|
107
|
+
header = JSON.parse(latin1FromBase64url(segments[0]));
|
|
108
|
+
claims = JSON.parse(utf8FromBase64url(segments[1]));
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return { ok: false, reason: 'malformed' };
|
|
112
|
+
}
|
|
113
|
+
if (!isJsonObject(header) || !isJsonObject(claims))
|
|
114
|
+
return { ok: false, reason: 'malformed' };
|
|
115
|
+
const decoded = { header, claims };
|
|
116
|
+
// jwt.js getKeyCallback: a falsy kid means "no kid", and every key is tried.
|
|
117
|
+
const kidNamesNoKey = Boolean(header.kid) && header.kid !== SANDBOX_KID;
|
|
118
|
+
if (kidNamesNoKey)
|
|
119
|
+
return { ok: false, reason: 'kid', ...decoded };
|
|
120
|
+
const expected = await sandboxSignature(`${segments[0]}.${segments[1]}`);
|
|
121
|
+
if (segments[2] !== expected)
|
|
122
|
+
return { ok: false, reason: 'signature', ...decoded };
|
|
123
|
+
return { ok: true, ...decoded };
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=app-check-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-check-token.js","sourceRoot":"","sources":["../../../src/sandbox/internal/app-check-token.ts"],"names":[],"mappings":"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"}
|
|
@@ -77,4 +77,5 @@ export { UNNAMED_DEFAULT_DATABASE_INSTANCE, createDatabaseInstanceRegistry, data
|
|
|
77
77
|
export { DEFAULT_DATABASE_RULES_FILE, databaseRulesConfig, type DatabaseRulesConfig, type DatabaseRulesConfigOptions, type DatabaseRulesFileTarget, type UnresolvedDatabaseRulesTarget, } from './database-rules-config.js';
|
|
78
78
|
export { parsePyricSandbox, isRemoteActivation, type PyricSandboxActivation } from './sandbox-activation.js';
|
|
79
79
|
export { clearProcessActivation, installProcessActivation, onProcessActivationEnd, processActivation, type ProcessActivation, } from './process-activation.js';
|
|
80
|
+
export { appCheckProjectNumber, checkAppCheckToken, mintAppCheckToken, signAppCheckToken, type AppCheckIdentity, type AppCheckTokenCheck, type AppCheckTokenClaims, type AppCheckTokenParts, type MintedAppCheckToken, } from './app-check-token.js';
|
|
80
81
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sandbox/internal/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sandbox/internal/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -118,4 +118,5 @@ export { UNNAMED_DEFAULT_DATABASE_INSTANCE, createDatabaseInstanceRegistry, data
|
|
|
118
118
|
export { DEFAULT_DATABASE_RULES_FILE, databaseRulesConfig, } from './database-rules-config.js';
|
|
119
119
|
export { parsePyricSandbox, isRemoteActivation } from './sandbox-activation.js';
|
|
120
120
|
export { clearProcessActivation, installProcessActivation, onProcessActivationEnd, processActivation, } from './process-activation.js';
|
|
121
|
+
export { appCheckProjectNumber, checkAppCheckToken, mintAppCheckToken, signAppCheckToken, } from './app-check-token.js';
|
|
121
122
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/sandbox/internal/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/sandbox/internal/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App Check errors with the codes, messages, and customData production
|
|
3
|
+
* throws (captures `app-check-client-initialize-twice` and
|
|
4
|
+
* `app-check-client-get-token-before-initialize`).
|
|
5
|
+
*/
|
|
6
|
+
import { FirebaseError } from '../sandbox/internal/firebase-error.js';
|
|
7
|
+
|
|
8
|
+
const MESSAGES = {
|
|
9
|
+
'already-initialized': (appName: string) =>
|
|
10
|
+
`You have already called initializeAppCheck() for FirebaseApp ${appName} with different options. To avoid this error, call initializeAppCheck() with the same options as when it was originally called. This will return the already initialized instance.`,
|
|
11
|
+
'use-before-activation': (appName: string) =>
|
|
12
|
+
`App Check is being used before initializeAppCheck() is called for FirebaseApp ${appName}. Call initializeAppCheck() before instantiating other Firebase services.`,
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
export type AppCheckErrorCode = keyof typeof MESSAGES;
|
|
16
|
+
|
|
17
|
+
export function appCheckError(code: AppCheckErrorCode, appName: string): FirebaseError {
|
|
18
|
+
const fullCode = `appCheck/${code}`;
|
|
19
|
+
return new FirebaseError(fullCode, `AppCheck: ${MESSAGES[code](appName)} (${fullCode}).`, { appName });
|
|
20
|
+
}
|
package/src/app-check/index.ts
CHANGED
|
@@ -1,41 +1,110 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `pyric/app-check
|
|
2
|
+
* `pyric/app-check`: the sandbox mirror of `firebase/app-check`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The sandbox has no attestation authority, so it behaves like production
|
|
5
|
+
* under a registered debug token: providers are accepted and never called,
|
|
6
|
+
* and every token request succeeds with a token of production's shape. The
|
|
7
|
+
* conformance rows are in packages/conformance/registry/app-check.ts and the
|
|
8
|
+
* suite in packages/pyric/test/app-check/oracle-conformance.test.ts.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
* `pyric` still loads; touching one throws `PyricDeferredApiError` naming this
|
|
11
|
-
* subpath. See `../deferred/entry.ts` for the full rationale.
|
|
12
|
-
*
|
|
13
|
-
* The value list is the exact public runtime surface of `firebase/app-check`
|
|
14
|
-
* (Firebase Web SDK 12.13.0). Keep it in sync when this entry graduates to a
|
|
15
|
-
* real mirror.
|
|
10
|
+
* The value surface is exactly `firebase/app-check` 12.13.0's.
|
|
16
11
|
*/
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
export
|
|
33
|
-
export type AppCheckToken
|
|
34
|
-
export type
|
|
35
|
-
|
|
36
|
-
export
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
export
|
|
41
|
-
|
|
12
|
+
import { getApp } from '../app/registry.js';
|
|
13
|
+
import type { FirebaseApp } from '../app/types.js';
|
|
14
|
+
import { appCheckError } from './errors.js';
|
|
15
|
+
import { CustomProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider, sameProvider, type AppCheckProvider } from './providers.js';
|
|
16
|
+
import {
|
|
17
|
+
activate,
|
|
18
|
+
addObserver,
|
|
19
|
+
cachedOrMint,
|
|
20
|
+
mintLimitedUse,
|
|
21
|
+
stateOf,
|
|
22
|
+
type AppCheckState,
|
|
23
|
+
type AppCheckTokenResult,
|
|
24
|
+
type TokenObserver,
|
|
25
|
+
} from './state.js';
|
|
26
|
+
|
|
27
|
+
export { CustomProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider };
|
|
28
|
+
export type { CustomProviderOptions, AppCheckTokenFromProvider as AppCheckToken } from './providers.js';
|
|
29
|
+
export type { AppCheckTokenResult } from './state.js';
|
|
30
|
+
|
|
31
|
+
export interface AppCheck {
|
|
32
|
+
readonly app: FirebaseApp;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface AppCheckOptions {
|
|
36
|
+
provider: AppCheckProvider;
|
|
37
|
+
isTokenAutoRefreshEnabled?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type AppCheckTokenListener = (token: AppCheckTokenResult) => void;
|
|
41
|
+
export type Unsubscribe = () => void;
|
|
42
|
+
export interface PartialObserver<T> {
|
|
43
|
+
next?: (value: T) => void;
|
|
44
|
+
error?: (error: Error) => void;
|
|
45
|
+
complete?: () => void;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
class AppCheckHandle implements AppCheck {
|
|
49
|
+
constructor(readonly app: FirebaseApp) {}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const handles = new WeakMap<FirebaseApp, AppCheckHandle>();
|
|
53
|
+
|
|
54
|
+
function hasSameOptions(state: AppCheckState, options: AppCheckOptions): boolean {
|
|
55
|
+
const refresh = options.isTokenAutoRefreshEnabled ?? false;
|
|
56
|
+
return state.initialAutoRefresh === refresh && sameProvider(state.provider, options.provider);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function initializeAppCheck(app: FirebaseApp | undefined, options: AppCheckOptions): AppCheck {
|
|
60
|
+
const target = app ?? getApp();
|
|
61
|
+
const existing = stateOf(target);
|
|
62
|
+
if (existing) {
|
|
63
|
+
if (!hasSameOptions(existing, options)) throw appCheckError('already-initialized', target.name);
|
|
64
|
+
return handles.get(target)!;
|
|
65
|
+
}
|
|
66
|
+
activate(target, options.provider, options.isTokenAutoRefreshEnabled ?? false);
|
|
67
|
+
const handle = new AppCheckHandle(target);
|
|
68
|
+
handles.set(target, handle);
|
|
69
|
+
return handle;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function activeState(appCheck: AppCheck): AppCheckState {
|
|
73
|
+
const state = stateOf(appCheck.app);
|
|
74
|
+
if (!state) throw appCheckError('use-before-activation', appCheck.app.name);
|
|
75
|
+
return state;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function getToken(appCheck: AppCheck, forceRefresh = false): Promise<AppCheckTokenResult> {
|
|
79
|
+
const state = activeState(appCheck);
|
|
80
|
+
return cachedOrMint(appCheck.app, state, forceRefresh);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function getLimitedUseToken(appCheck: AppCheck): Promise<AppCheckTokenResult> {
|
|
84
|
+
activeState(appCheck);
|
|
85
|
+
return mintLimitedUse(appCheck.app);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function setTokenAutoRefreshEnabled(appCheck: AppCheck, isTokenAutoRefreshEnabled: boolean): void {
|
|
89
|
+
activeState(appCheck).isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function toObserver(
|
|
93
|
+
onNextOrObserver: AppCheckTokenListener | PartialObserver<AppCheckTokenResult>,
|
|
94
|
+
onError?: (error: Error) => void,
|
|
95
|
+
onCompletion?: () => void,
|
|
96
|
+
): TokenObserver {
|
|
97
|
+
if (typeof onNextOrObserver === 'function') {
|
|
98
|
+
return { next: onNextOrObserver, error: onError, complete: onCompletion };
|
|
99
|
+
}
|
|
100
|
+
return { next: onNextOrObserver.next ?? (() => {}), error: onNextOrObserver.error, complete: onNextOrObserver.complete };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function onTokenChanged(
|
|
104
|
+
appCheck: AppCheck,
|
|
105
|
+
onNextOrObserver: AppCheckTokenListener | PartialObserver<AppCheckTokenResult>,
|
|
106
|
+
onError?: (error: Error) => void,
|
|
107
|
+
onCompletion?: () => void,
|
|
108
|
+
): Unsubscribe {
|
|
109
|
+
return addObserver(activeState(appCheck), toObserver(onNextOrObserver, onError, onCompletion));
|
|
110
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The three attestation providers. The sandbox has no attestation service, so
|
|
3
|
+
* it never calls a provider, as production never does under a debug token
|
|
4
|
+
* (capture `app-check-client-debug-get-token`, `customProviderCalls: 0`).
|
|
5
|
+
* `isEqual` decides whether a second `initializeAppCheck` has the same options.
|
|
6
|
+
*/
|
|
7
|
+
export interface AppCheckTokenFromProvider {
|
|
8
|
+
readonly token: string;
|
|
9
|
+
readonly expireTimeMillis: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface CustomProviderOptions {
|
|
13
|
+
getToken: () => Promise<AppCheckTokenFromProvider>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface ComparableProvider {
|
|
17
|
+
isEqual(other: unknown): boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class ReCaptchaV3Provider implements ComparableProvider {
|
|
21
|
+
constructor(private readonly siteKey: string) {}
|
|
22
|
+
isEqual(other: unknown): boolean {
|
|
23
|
+
return other instanceof ReCaptchaV3Provider && other.siteKey === this.siteKey;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class ReCaptchaEnterpriseProvider implements ComparableProvider {
|
|
28
|
+
constructor(private readonly siteKey: string) {}
|
|
29
|
+
isEqual(other: unknown): boolean {
|
|
30
|
+
return other instanceof ReCaptchaEnterpriseProvider && other.siteKey === this.siteKey;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class CustomProvider implements ComparableProvider {
|
|
35
|
+
constructor(private readonly options: CustomProviderOptions) {}
|
|
36
|
+
/** Upstream compares the getToken functions by source text, so a provider rebuilt by the same factory is equal. */
|
|
37
|
+
isEqual(other: unknown): boolean {
|
|
38
|
+
return other instanceof CustomProvider && String(other.options.getToken) === String(this.options.getToken);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type AppCheckProvider = ReCaptchaV3Provider | ReCaptchaEnterpriseProvider | CustomProvider;
|
|
43
|
+
|
|
44
|
+
export function sameProvider(a: AppCheckProvider, b: AppCheckProvider): boolean {
|
|
45
|
+
return a.isEqual(b);
|
|
46
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-app App Check state: the activation options, the cached token, and the
|
|
3
|
+
* token listeners. Keyed by the app object, as upstream keys it.
|
|
4
|
+
*/
|
|
5
|
+
import type { FirebaseApp } from '../app/types.js';
|
|
6
|
+
import { mintAppCheckToken, type MintedAppCheckToken as MintedToken } from '../sandbox/internal/app-check-token.js';
|
|
7
|
+
|
|
8
|
+
/** Web App Check tokens live one hour (capture `app-check-client-debug-get-token`). */
|
|
9
|
+
const TTL_SECONDS = 3600;
|
|
10
|
+
import type { AppCheckProvider } from './providers.js';
|
|
11
|
+
|
|
12
|
+
export interface AppCheckTokenResult {
|
|
13
|
+
readonly token: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TokenObserver {
|
|
17
|
+
next: (result: AppCheckTokenResult) => void;
|
|
18
|
+
error?: (error: Error) => void;
|
|
19
|
+
complete?: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface AppCheckState {
|
|
23
|
+
provider: AppCheckProvider;
|
|
24
|
+
/** The option `initializeAppCheck` was called with; a later call is compared with this. */
|
|
25
|
+
readonly initialAutoRefresh: boolean;
|
|
26
|
+
isTokenAutoRefreshEnabled: boolean;
|
|
27
|
+
cached: MintedToken | null;
|
|
28
|
+
observers: Set<TokenObserver>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const states = new WeakMap<FirebaseApp, AppCheckState>();
|
|
32
|
+
|
|
33
|
+
export function stateOf(app: FirebaseApp): AppCheckState | undefined {
|
|
34
|
+
return states.get(app);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function activate(app: FirebaseApp, provider: AppCheckProvider, isTokenAutoRefreshEnabled: boolean): AppCheckState {
|
|
38
|
+
const state: AppCheckState = { provider, initialAutoRefresh: isTokenAutoRefreshEnabled, isTokenAutoRefreshEnabled, cached: null, observers: new Set() };
|
|
39
|
+
states.set(app, state);
|
|
40
|
+
return state;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function identityOf(app: FirebaseApp) {
|
|
44
|
+
const options = app.options as { appId?: string; projectId?: string };
|
|
45
|
+
return { appId: options.appId ?? '', projectId: options.projectId ?? '' };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Delivers a token to observers off the caller's stack, as the SDK does. */
|
|
49
|
+
function notify(observers: Iterable<TokenObserver>, result: AppCheckTokenResult): void {
|
|
50
|
+
for (const observer of observers) {
|
|
51
|
+
queueMicrotask(() => observer.next(result));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isValid(token: MintedToken | null, nowMillis: number): token is MintedToken {
|
|
56
|
+
return token !== null && token.expireTimeMillis > nowMillis;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function cachedOrMint(app: FirebaseApp, state: AppCheckState, forceRefresh: boolean): Promise<AppCheckTokenResult> {
|
|
60
|
+
const now = Date.now();
|
|
61
|
+
const reuse = !forceRefresh && isValid(state.cached, now);
|
|
62
|
+
if (reuse) return { token: state.cached!.token };
|
|
63
|
+
state.cached = await mintAppCheckToken(identityOf(app), TTL_SECONDS, now);
|
|
64
|
+
const result = { token: state.cached.token };
|
|
65
|
+
notify(state.observers, result);
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function mintLimitedUse(app: FirebaseApp): Promise<AppCheckTokenResult> {
|
|
70
|
+
return { token: (await mintAppCheckToken(identityOf(app), TTL_SECONDS)).token };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function addObserver(state: AppCheckState, observer: TokenObserver): () => void {
|
|
74
|
+
state.observers.add(observer);
|
|
75
|
+
if (isValid(state.cached, Date.now())) notify([observer], { token: state.cached.token });
|
|
76
|
+
return () => {
|
|
77
|
+
state.observers.delete(observer);
|
|
78
|
+
};
|
|
79
|
+
}
|
package/src/deferred/entry.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The shared factory behind pyric's *deferred* Firebase Web SDK subpaths —
|
|
3
|
-
* `pyric/functions`, `pyric/analytics`,
|
|
3
|
+
* `pyric/functions`, `pyric/analytics`,
|
|
4
4
|
* `pyric/firestore/lite`, `pyric/performance` and `pyric/remote-config`.
|
|
5
5
|
*
|
|
6
6
|
* WHY THESE EXIST AT ALL. pyric is a symbol-for-symbol drop-in for the
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandbox App Check tokens, shared by the web mirror (`pyric/app-check`) and
|
|
3
|
+
* the admin mirror (`pyric-admin/app-check`) so a token minted on either plane
|
|
4
|
+
* verifies on the other, as production's do (capture
|
|
5
|
+
* `app-check-admin-verify-token`, `debugExchanged`).
|
|
6
|
+
*
|
|
7
|
+
* Shape (captures `app-check-client-debug-get-token`,
|
|
8
|
+
* `app-check-admin-create-token-shape`): a three-segment JWT, header `alg`
|
|
9
|
+
* RS256, `typ` JWT, a `kid`; claims `aud`, `exp`, `iat`, `iss`, `jti`,
|
|
10
|
+
* `provider`, `sub`; `iss` and `aud` name the project number from the app id.
|
|
11
|
+
*
|
|
12
|
+
* The signature is not RSA. It is a 256-byte SHA-256 expansion over the
|
|
13
|
+
* signing input and a fixed sandbox key, the length of a real RS256
|
|
14
|
+
* signature, so any edit to the header, payload, or signature fails
|
|
15
|
+
* verification. It is not a security boundary: anyone can mint one.
|
|
16
|
+
*/
|
|
17
|
+
const ISSUER = 'https://firebaseappcheck.googleapis.com';
|
|
18
|
+
const SANDBOX_KID = 'pyric-sandbox';
|
|
19
|
+
const SANDBOX_KEY = 'pyric-sandbox-app-check-signing-key';
|
|
20
|
+
const SIGNATURE_BLOCKS = 8;
|
|
21
|
+
|
|
22
|
+
export interface AppCheckIdentity {
|
|
23
|
+
appId: string;
|
|
24
|
+
projectId: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface AppCheckTokenClaims {
|
|
28
|
+
sub: string;
|
|
29
|
+
aud: string[];
|
|
30
|
+
provider: string;
|
|
31
|
+
iss: string;
|
|
32
|
+
exp: number;
|
|
33
|
+
iat: number;
|
|
34
|
+
jti: string;
|
|
35
|
+
[claim: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface MintedAppCheckToken {
|
|
39
|
+
token: string;
|
|
40
|
+
expireTimeMillis: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function base64url(bytes: Uint8Array): string {
|
|
44
|
+
let binary = '';
|
|
45
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
46
|
+
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** jws `JWS_REGEX`: base64url characters only, header and payload non-empty, signature optional. */
|
|
50
|
+
const JWS_SHAPE = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;
|
|
51
|
+
|
|
52
|
+
/** A base64url segment as Latin-1 text, one character per byte, as jws reads a header (`toString('binary')`). */
|
|
53
|
+
function latin1FromBase64url(text: string): string {
|
|
54
|
+
const padded = text.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(text.length / 4) * 4, '=');
|
|
55
|
+
return atob(padded);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* A base64url segment as UTF-8, as jws reads a payload (`toString('utf8')`):
|
|
60
|
+
* the inverse of {@link encodeJson}, with invalid bytes replaced by U+FFFD as
|
|
61
|
+
* Buffer does. Uses `atob` and `TextDecoder` only, so it runs the same in a
|
|
62
|
+
* browser or worker.
|
|
63
|
+
*/
|
|
64
|
+
function utf8FromBase64url(text: string): string {
|
|
65
|
+
const binary = latin1FromBase64url(text);
|
|
66
|
+
const bytes = new Uint8Array(binary.length);
|
|
67
|
+
for (let index = 0; index < binary.length; index++) bytes[index] = binary.charCodeAt(index);
|
|
68
|
+
return new TextDecoder('utf-8').decode(bytes);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isJsonObject(value: unknown): value is Record<string, unknown> {
|
|
72
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function encodeJson(value: unknown): string {
|
|
76
|
+
return base64url(new TextEncoder().encode(JSON.stringify(value)));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function randomId(): string {
|
|
80
|
+
const bytes = new Uint8Array(32);
|
|
81
|
+
crypto.getRandomValues(bytes);
|
|
82
|
+
return base64url(bytes);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function sandboxSignature(signingInput: string): Promise<string> {
|
|
86
|
+
const blocks: Uint8Array[] = [];
|
|
87
|
+
for (let block = 0; block < SIGNATURE_BLOCKS; block++) {
|
|
88
|
+
const data = new TextEncoder().encode(`${block}.${SANDBOX_KEY}.${signingInput}`);
|
|
89
|
+
blocks.push(new Uint8Array(await crypto.subtle.digest('SHA-256', data)));
|
|
90
|
+
}
|
|
91
|
+
const out = new Uint8Array(blocks.length * 32);
|
|
92
|
+
blocks.forEach((bytes, index) => out.set(bytes, index * 32));
|
|
93
|
+
return base64url(out);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** The project number a Firebase app id carries: `1:<projectNumber>:<platform>:<hash>`. */
|
|
97
|
+
export function appCheckProjectNumber(appId: string): string {
|
|
98
|
+
return appId.split(':')[1] ?? '';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function mintAppCheckToken(
|
|
102
|
+
identity: AppCheckIdentity,
|
|
103
|
+
ttlSeconds: number,
|
|
104
|
+
nowMillis: number = Date.now(),
|
|
105
|
+
): Promise<MintedAppCheckToken> {
|
|
106
|
+
const iat = Math.floor(nowMillis / 1000);
|
|
107
|
+
const exp = iat + ttlSeconds;
|
|
108
|
+
const projectNumber = appCheckProjectNumber(identity.appId);
|
|
109
|
+
const claims: AppCheckTokenClaims = {
|
|
110
|
+
sub: identity.appId,
|
|
111
|
+
aud: [`projects/${projectNumber}`, `projects/${identity.projectId}`],
|
|
112
|
+
provider: 'pyric-sandbox',
|
|
113
|
+
iss: `${ISSUER}/${projectNumber}`,
|
|
114
|
+
exp,
|
|
115
|
+
iat,
|
|
116
|
+
jti: randomId(),
|
|
117
|
+
};
|
|
118
|
+
const token = await signAppCheckToken({ alg: 'RS256', kid: SANDBOX_KID, typ: 'JWT' }, claims);
|
|
119
|
+
return { token, expireTimeMillis: exp * 1000 };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Signs any header and claims with the sandbox key. Minting uses it; tests use it to build tokens production could not issue. */
|
|
123
|
+
export async function signAppCheckToken(header: Record<string, unknown>, claims: Record<string, unknown>): Promise<string> {
|
|
124
|
+
const signingInput = `${encodeJson(header)}.${encodeJson(claims)}`;
|
|
125
|
+
return `${signingInput}.${await sandboxSignature(signingInput)}`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** A decoded token's header and claims, unchecked: any field may be missing or of any type. */
|
|
129
|
+
export interface AppCheckTokenParts {
|
|
130
|
+
header: Readonly<Record<string, unknown>>;
|
|
131
|
+
claims: Readonly<Record<string, unknown>>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export type AppCheckTokenCheck =
|
|
135
|
+
| ({ ok: true } & AppCheckTokenParts)
|
|
136
|
+
| ({ ok: false; reason: 'kid' | 'signature' } & AppCheckTokenParts)
|
|
137
|
+
| { ok: false; reason: 'malformed' };
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Decodes a sandbox token and checks its key and signature, in
|
|
141
|
+
* firebase-admin's order: a `kid` must name the sandbox key, and a token with
|
|
142
|
+
* no `kid` is checked against it, as firebase-admin tries every key. The
|
|
143
|
+
* decoded header and claims come back whenever the token decodes; `alg`,
|
|
144
|
+
* audience, subject and expiry are the caller's rules.
|
|
145
|
+
*/
|
|
146
|
+
export async function checkAppCheckToken(token: string): Promise<AppCheckTokenCheck> {
|
|
147
|
+
if (!JWS_SHAPE.test(token)) return { ok: false, reason: 'malformed' };
|
|
148
|
+
const segments = token.split('.');
|
|
149
|
+
let header: unknown;
|
|
150
|
+
let claims: unknown;
|
|
151
|
+
try {
|
|
152
|
+
header = JSON.parse(latin1FromBase64url(segments[0]!));
|
|
153
|
+
claims = JSON.parse(utf8FromBase64url(segments[1]!));
|
|
154
|
+
} catch {
|
|
155
|
+
return { ok: false, reason: 'malformed' };
|
|
156
|
+
}
|
|
157
|
+
if (!isJsonObject(header) || !isJsonObject(claims)) return { ok: false, reason: 'malformed' };
|
|
158
|
+
const decoded = { header, claims };
|
|
159
|
+
// jwt.js getKeyCallback: a falsy kid means "no kid", and every key is tried.
|
|
160
|
+
const kidNamesNoKey = Boolean(header.kid) && header.kid !== SANDBOX_KID;
|
|
161
|
+
if (kidNamesNoKey) return { ok: false, reason: 'kid', ...decoded };
|
|
162
|
+
const expected = await sandboxSignature(`${segments[0]}.${segments[1]}`);
|
|
163
|
+
if (segments[2] !== expected) return { ok: false, reason: 'signature', ...decoded };
|
|
164
|
+
return { ok: true, ...decoded };
|
|
165
|
+
}
|
|
@@ -227,3 +227,14 @@ export {
|
|
|
227
227
|
processActivation,
|
|
228
228
|
type ProcessActivation,
|
|
229
229
|
} from './process-activation.js';
|
|
230
|
+
export {
|
|
231
|
+
appCheckProjectNumber,
|
|
232
|
+
checkAppCheckToken,
|
|
233
|
+
mintAppCheckToken,
|
|
234
|
+
signAppCheckToken,
|
|
235
|
+
type AppCheckIdentity,
|
|
236
|
+
type AppCheckTokenCheck,
|
|
237
|
+
type AppCheckTokenClaims,
|
|
238
|
+
type AppCheckTokenParts,
|
|
239
|
+
type MintedAppCheckToken,
|
|
240
|
+
} from './app-check-token.js';
|