pyric-admin 0.1.0-alpha.32 → 0.1.0-alpha.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,130 +1,110 @@
1
1
  /**
2
- * Token format minted by `createCustomToken` and parsed by
3
- * `verifyIdToken`. Exported as a constant so tests can lock the shape.
2
+ * The ID token check behind `pyric-admin/auth` `verifyIdToken`.
4
3
  *
5
- * Layout: `pyric-sandbox-custom:${uid}:${jsonClaims}`
6
- *
7
- * - The prefix lets `verifyIdToken` reject foreign tokens with a clear
8
- * "not a sandbox token" error rather than NaN'ing out.
9
- * - `uid` is colon-free per the auto-uid format above.
10
- * - `jsonClaims` is the JSON-stringified developer claims (or `{}` when
11
- * none were provided). Round-trips losslessly through `JSON.parse`.
12
- *
13
- * NOT a JWT. NOT signed. Do not use this token format to talk to any
14
- * real Firebase service — it only round-trips through this same
15
- * sandbox backend.
4
+ * The only token that verifies is the JWT pyric's Auth mints
5
+ * (`pyric/sandbox/internal` `mintIdToken`), checked by the shared
6
+ * {@link checkIdToken} and then by firebase-admin 13.10.0's rules, in its
7
+ * order (lib/auth/token-verifier.js `verifyContent` and `verifySignature`,
8
+ * lib/utils/jwt.js, and jsonwebtoken's `nbf` and `exp`). A plain string, or
9
+ * the client token shape from before #1836, fails to decode, and a custom
10
+ * token is refused as one, as in production (#1949, #1952).
16
11
  */
17
- export const SANDBOX_TOKEN_PREFIX = 'pyric-sandbox-custom';
18
- function resolveStringClaim(claims, key, fallback) {
19
- const val = claims[key];
20
- const hasStringValue = typeof val === 'string';
21
- return hasStringValue ? val : fallback;
12
+ import { checkIdToken, CUSTOM_TOKEN_AUDIENCE } from 'pyric/sandbox/internal';
13
+ const ID_TOKEN_ISSUER = 'https://securetoken.google.com/';
14
+ const MAX_SUBJECT_LENGTH = 128;
15
+ const DOCS = ' See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.';
16
+ const PROJECT_MATCH = ' Make sure the ID token comes from the same Firebase project as the service account used to authenticate this SDK.';
17
+ const MESSAGES = {
18
+ decode: `Decoding Firebase ID token failed. Make sure you passed the entire string JWT which represents an ID token.${DOCS}`,
19
+ customToken: `verifyIdToken() expects an ID token, but was given a custom token.${DOCS}`,
20
+ legacyCustomToken: `verifyIdToken() expects an ID token, but was given a legacy custom token.${DOCS}`,
21
+ noKid: `Firebase ID token has no "kid" claim.${DOCS}`,
22
+ algorithm: (alg) => `Firebase ID token has incorrect algorithm. Expected "RS256" but got "${String(alg)}".${DOCS}`,
23
+ audience: (projectId, aud) => `Firebase ID token has incorrect "aud" (audience) claim. Expected "${projectId}" but got "${String(aud)}".${PROJECT_MATCH}${DOCS}`,
24
+ issuer: (projectId, iss) => `Firebase ID token has incorrect "iss" (issuer) claim. Expected "${ID_TOKEN_ISSUER}${projectId}" but got "${String(iss)}".${PROJECT_MATCH}${DOCS}`,
25
+ noSub: `Firebase ID token has no "sub" (subject) claim.${DOCS}`,
26
+ emptySub: `Firebase ID token has an empty "sub" (subject) claim.${DOCS}`,
27
+ longSub: `Firebase ID token has a "sub" (subject) claim longer than 128 characters.${DOCS}`,
28
+ unknownKid: 'Firebase ID token has "kid" claim which does not correspond to a known public key. Most likely the ID token is expired, so get a fresh token from your client app and try again.',
29
+ signature: `Firebase ID token has invalid signature.${DOCS}`,
30
+ expired: `Firebase ID token has expired. Get a fresh ID token from your client app and try again (auth/id-token-expired).${DOCS}`,
31
+ };
32
+ function refused(message) {
33
+ return { ok: false, code: 'argument-error', message };
22
34
  }
23
- function resolveNumberClaim(claims, key, fallback) {
24
- const val = claims[key];
25
- const hasNumberValue = typeof val === 'number';
26
- return hasNumberValue ? val : fallback;
35
+ /** token-verifier.js: a missing `kid` names a custom token, a legacy custom token, or neither. */
36
+ function missingKidMessage(header, claims) {
37
+ if (claims.aud === CUSTOM_TOKEN_AUDIENCE)
38
+ return MESSAGES.customToken;
39
+ const legacyData = claims.d;
40
+ const isLegacyCustomToken = header.alg === 'HS256' && claims.v === 0 && typeof legacyData === 'object' && legacyData !== null && 'uid' in legacyData;
41
+ if (isLegacyCustomToken)
42
+ return MESSAGES.legacyCustomToken;
43
+ return MESSAGES.noKid;
27
44
  }
28
- function resolveUid(idToken, firstColon, claims) {
29
- const rawSub = claims['sub'];
30
- const hasExplicitSubjectClaim = typeof rawSub === 'string';
31
- if (hasExplicitSubjectClaim) {
32
- return rawSub;
33
- }
34
- const prefixSegment = idToken.slice('sandbox-id-token-'.length, firstColon);
35
- const lastHyphen = prefixSegment.lastIndexOf('-');
36
- const hasHyphenatedSerialSuffix = lastHyphen > 0;
37
- if (hasHyphenatedSerialSuffix) {
38
- return prefixSegment.slice(0, lastHyphen);
39
- }
40
- return prefixSegment;
45
+ /** Auth blocking events with no user record, whose `sub` firebase-admin leaves unchecked. */
46
+ function skipsSubjectCheck(claims) {
47
+ return claims.event_type === 'beforeSendSms' || claims.event_type === 'beforeSendEmail';
41
48
  }
42
- function resolveFirebaseClaim(claims) {
43
- const rawFirebase = claims['firebase'];
44
- const isMissingFirebaseClaim = !rawFirebase || typeof rawFirebase !== 'object';
45
- if (isMissingFirebaseClaim) {
46
- return { identities: {}, sign_in_provider: 'custom' };
47
- }
48
- const fb = rawFirebase;
49
- const signInProvider = resolveStringClaim(fb, 'sign_in_provider', 'custom');
50
- const rawIdentities = fb['identities'];
51
- const isMissingIdentitiesMap = !rawIdentities || typeof rawIdentities !== 'object';
52
- if (isMissingIdentitiesMap) {
53
- return { identities: {}, sign_in_provider: signInProvider };
54
- }
55
- return { identities: rawIdentities, sign_in_provider: signInProvider };
49
+ function subjectMessage(sub) {
50
+ if (typeof sub !== 'string')
51
+ return MESSAGES.noSub;
52
+ if (sub === '')
53
+ return MESSAGES.emptySub;
54
+ if (sub.length > MAX_SUBJECT_LENGTH)
55
+ return MESSAGES.longSub;
56
+ return undefined;
57
+ }
58
+ /** token-verifier.js `verifyContent`: `kid`, `alg`, `aud`, `iss`, then `sub`; the first failure wins. */
59
+ function contentMessage(header, claims, projectId) {
60
+ if (header.kid === undefined)
61
+ return missingKidMessage(header, claims);
62
+ if (header.alg !== 'RS256')
63
+ return MESSAGES.algorithm(header.alg);
64
+ if (claims.aud !== projectId)
65
+ return MESSAGES.audience(projectId, claims.aud);
66
+ if (claims.iss !== `${ID_TOKEN_ISSUER}${projectId}`)
67
+ return MESSAGES.issuer(projectId, claims.iss);
68
+ if (skipsSubjectCheck(claims))
69
+ return undefined;
70
+ return subjectMessage(claims.sub);
71
+ }
72
+ /** jsonwebtoken's `nbf` rule, which runs before `exp`; firebase-admin reports a failure as an invalid signature. */
73
+ function isNotYetValid(nbf, nowSec) {
74
+ if (nbf === undefined)
75
+ return false;
76
+ return typeof nbf !== 'number' || nbf > nowSec;
77
+ }
78
+ /** jsonwebtoken's `exp` rule: an absent `exp` never expires, and a non-number is an invalid signature. */
79
+ function expiryVerdict(exp, nowSec) {
80
+ if (exp === undefined)
81
+ return undefined;
82
+ if (typeof exp !== 'number')
83
+ return refused(MESSAGES.signature);
84
+ const hasExpired = nowSec >= exp;
85
+ if (hasExpired)
86
+ return { ok: false, code: 'id-token-expired', message: MESSAGES.expired };
87
+ return undefined;
88
+ }
89
+ /**
90
+ * Checks an ID token for `projectId` at `nowSec`, in firebase-admin's order:
91
+ * decoding, the content rules, the key and signature, then `nbf` and `exp`.
92
+ */
93
+ export async function checkClientIdToken(idToken, projectId, nowSec) {
94
+ const check = await checkIdToken(idToken);
95
+ if (!check.ok && check.reason === 'malformed')
96
+ return refused(MESSAGES.decode);
97
+ const contentFailure = contentMessage(check.header, check.claims, projectId);
98
+ if (contentFailure !== undefined)
99
+ return refused(contentFailure);
100
+ if (!check.ok)
101
+ return refused(check.reason === 'kid' ? MESSAGES.unknownKid : MESSAGES.signature);
102
+ if (isNotYetValid(check.claims.nbf, nowSec))
103
+ return refused(MESSAGES.signature);
104
+ const expired = expiryVerdict(check.claims.exp, nowSec);
105
+ if (expired !== undefined)
106
+ return expired;
107
+ const token = { ...check.claims, uid: check.claims.sub };
108
+ return { ok: true, token };
56
109
  }
57
- const customTokenDecoder = {
58
- name: 'custom-token',
59
- prefix: `${SANDBOX_TOKEN_PREFIX}:`,
60
- decode(idToken, nowSec) {
61
- const firstColon = idToken.indexOf(':');
62
- const secondColon = idToken.indexOf(':', firstColon + 1);
63
- const isMissingClaimsSegment = secondColon < 0;
64
- if (isMissingClaimsSegment) {
65
- throw new Error(`pyric-admin/auth: verifyIdToken received a malformed sandbox token (missing claims segment): ${idToken}`);
66
- }
67
- const uid = idToken.slice(firstColon + 1, secondColon);
68
- const jsonClaims = idToken.slice(secondColon + 1);
69
- let claims;
70
- try {
71
- claims = JSON.parse(jsonClaims);
72
- }
73
- catch (e) {
74
- throw new Error(`pyric-admin/auth: verifyIdToken failed to parse sandbox token claims as JSON: ${e.message}`);
75
- }
76
- return {
77
- aud: 'pyric-sandbox',
78
- auth_time: nowSec,
79
- exp: nowSec + 3600,
80
- firebase: {
81
- identities: {},
82
- sign_in_provider: 'custom',
83
- },
84
- iat: nowSec,
85
- iss: 'pyric-sandbox',
86
- sub: uid,
87
- uid,
88
- ...claims,
89
- };
90
- },
91
- };
92
- const clientIdTokenDecoder = {
93
- name: 'client-id-token',
94
- prefix: 'sandbox-id-token-',
95
- decode(idToken, nowSec) {
96
- const firstColon = idToken.indexOf(':');
97
- const isMissingClaimsSegment = firstColon < 0;
98
- if (isMissingClaimsSegment) {
99
- throw new Error(`pyric-admin/auth: verifyIdToken received a malformed client ID token (missing claims segment after colon): ${idToken}`);
100
- }
101
- const jsonClaims = idToken.slice(firstColon + 1);
102
- let claims;
103
- try {
104
- claims = JSON.parse(jsonClaims);
105
- }
106
- catch (e) {
107
- throw new Error(`pyric-admin/auth: verifyIdToken failed to parse client ID token claims as JSON: ${e.message}`);
108
- }
109
- const uid = resolveUid(idToken, firstColon, claims);
110
- const aud = resolveStringClaim(claims, 'aud', 'pyric-sandbox');
111
- const iss = resolveStringClaim(claims, 'iss', 'https://sandbox.pyric.dev');
112
- const exp = resolveNumberClaim(claims, 'exp', nowSec + 3600);
113
- const iat = resolveNumberClaim(claims, 'iat', nowSec);
114
- const authTime = resolveNumberClaim(claims, 'auth_time', nowSec);
115
- const firebase = resolveFirebaseClaim(claims);
116
- return {
117
- ...claims,
118
- aud,
119
- auth_time: authTime,
120
- exp,
121
- firebase,
122
- iat,
123
- iss,
124
- sub: uid,
125
- uid,
126
- };
127
- },
128
- };
129
- export const TOKEN_DECODERS = [customTokenDecoder, clientIdTokenDecoder];
130
110
  //# sourceMappingURL=token-decoders.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"token-decoders.js","sourceRoot":"","sources":["../../src/auth/token-decoders.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"token-decoders.js","sourceRoot":"","sources":["../../src/auth/token-decoders.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,52 @@
1
1
  /**
2
- * Stateless ID token verification for `pyric-admin/auth`.
3
- * Routes token parsing across recognized decoder strategies.
2
+ * `verifyIdToken` for `pyric-admin/auth`, shared by the in-process and remote
3
+ * arms. Each arm passes the project the token must be scoped to and the
4
+ * current time on its own clock.
4
5
  */
6
+ import type { AuthAccountStanding } from 'pyric/sandbox/internal';
7
+ import { PrefixedFirebaseError } from '../app/firebase-error.js';
5
8
  import type { DecodedIdToken } from './types.js';
9
+ import { type IdTokenFailureCode } from './token-decoders.js';
10
+ /** The codes `checkRevoked` and `revokeRefreshTokens` add to a token check's. */
11
+ type AccountFailureCode = 'user-not-found' | 'user-disabled' | 'id-token-revoked' | 'invalid-uid';
12
+ /** firebase-admin's FirebaseAuthError: a PrefixedFirebaseError with prefix `auth`. */
13
+ export declare class FirebaseAuthError extends PrefixedFirebaseError {
14
+ constructor(code: IdTokenFailureCode | AccountFailureCode, message: string);
15
+ }
16
+ /** What one verification checks against. */
17
+ export interface IdTokenExpectation {
18
+ /** The project the token's `aud` and `iss` must name. */
19
+ projectId: string;
20
+ /** The current time, in epoch milliseconds, that `nbf` and `exp` are read against. */
21
+ nowMs: number;
22
+ }
6
23
  /**
7
- * Parse a token minted by `createCustomToken` or a client ID token
8
- * minted by `pyric/auth`'s `getIdToken()`. Routes to the appropriate
9
- * modular token decoder based on token prefix.
24
+ * Throws `auth/argument-error` synchronously for a token that is not a string,
25
+ * as firebase-admin's `verifyJWT` does, so an arm that reads its clock before
26
+ * verifying can check the argument first.
27
+ */
28
+ export declare function assertIdTokenArgument(idToken: unknown): void;
29
+ /**
30
+ * Verifies an ID token minted by pyric's Auth for `expected.projectId`.
10
31
  *
11
- * Throws on any token that doesn't match a recognized sandbox prefix —
12
- * including real JWTs that another verifier would parse. The sandbox
13
- * backends are intentionally not drop-ins for production verification.
32
+ * A token that is not a string throws `auth/argument-error` synchronously, as
33
+ * firebase-admin's `verifyJWT` does. Every other failure rejects with
34
+ * `auth/argument-error`, or `auth/id-token-expired` for an expired token.
35
+ */
36
+ export declare function verifySandboxIdToken(idToken: string, expected: IdTokenExpectation): Promise<DecodedIdToken>;
37
+ /**
38
+ * firebase-admin's answer for a uid that is not a non-empty string of at most
39
+ * 128 characters (13.10.0 `validator.isUid`), checked before any request.
40
+ */
41
+ export declare function invalidUid(uid: unknown): FirebaseAuthError | null;
42
+ /** firebase-admin's `getUser` answer for a uid with no record. */
43
+ export declare function userNotFound(): FirebaseAuthError;
44
+ /**
45
+ * firebase-admin's `verifyDecodedJWTNotRevokedOrDisabled` (13.10.0
46
+ * `lib/auth/base-auth.js`), the `checkRevoked` step: the account must exist,
47
+ * be enabled, and have no revocation after the token's `auth_time`, compared
48
+ * in whole seconds as production stores it.
14
49
  */
15
- export declare function verifySandboxIdToken(idToken: string): Promise<DecodedIdToken>;
50
+ export declare function assertNotRevokedOrDisabled(decoded: DecodedIdToken, standing: AuthAccountStanding): DecodedIdToken;
51
+ export {};
16
52
  //# sourceMappingURL=verify-token.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify-token.d.ts","sourceRoot":"","sources":["../../src/auth/verify-token.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAyB7E"}
1
+ {"version":3,"file":"verify-token.d.ts","sourceRoot":"","sources":["../../src/auth/verify-token.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAElF,iFAAiF;AACjF,KAAK,kBAAkB,GAAG,gBAAgB,GAAG,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC;AAElG,sFAAsF;AACtF,qBAAa,iBAAkB,SAAQ,qBAAqB;gBAC9C,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,OAAO,EAAE,MAAM;CAG3E;AAED,4CAA4C;AAC5C,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,KAAK,EAAE,MAAM,CAAC;CACf;AAID;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAG5D;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CAO3G;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,GAAG,IAAI,CAIjE;AAED,kEAAkE;AAClE,wBAAgB,YAAY,IAAI,iBAAiB,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,mBAAmB,GAAG,cAAc,CAQjH"}
@@ -1,32 +1,68 @@
1
- import { SANDBOX_TOKEN_PREFIX, TOKEN_DECODERS } from './token-decoders.js';
1
+ import { PrefixedFirebaseError } from '../app/firebase-error.js';
2
+ import { checkClientIdToken } from './token-decoders.js';
3
+ /** firebase-admin's FirebaseAuthError: a PrefixedFirebaseError with prefix `auth`. */
4
+ export class FirebaseAuthError extends PrefixedFirebaseError {
5
+ constructor(code, message) {
6
+ super('auth', code, message);
7
+ }
8
+ }
9
+ const NOT_A_STRING = 'First argument to verifyIdToken() must be a Firebase ID token string.';
2
10
  /**
3
- * Parse a token minted by `createCustomToken` or a client ID token
4
- * minted by `pyric/auth`'s `getIdToken()`. Routes to the appropriate
5
- * modular token decoder based on token prefix.
6
- *
7
- * Throws on any token that doesn't match a recognized sandbox prefix —
8
- * including real JWTs that another verifier would parse. The sandbox
9
- * backends are intentionally not drop-ins for production verification.
11
+ * Throws `auth/argument-error` synchronously for a token that is not a string,
12
+ * as firebase-admin's `verifyJWT` does, so an arm that reads its clock before
13
+ * verifying can check the argument first.
10
14
  */
11
- export function verifySandboxIdToken(idToken) {
15
+ export function assertIdTokenArgument(idToken) {
12
16
  const isInvalidTokenArgument = typeof idToken !== 'string';
13
- if (isInvalidTokenArgument) {
14
- return Promise.reject(new Error('pyric-admin/auth: verifyIdToken expects a string argument.'));
15
- }
16
- const nowSec = Math.floor(Date.now() / 1000);
17
- for (const decoder of TOKEN_DECODERS) {
18
- const matchesDecoderPrefix = idToken.startsWith(decoder.prefix);
19
- if (matchesDecoderPrefix) {
20
- try {
21
- return Promise.resolve(decoder.decode(idToken, nowSec));
22
- }
23
- catch (error) {
24
- return Promise.reject(error);
25
- }
26
- }
27
- }
28
- return Promise.reject(new Error('pyric-admin/auth: verifyIdToken on the sandbox backend only ' +
29
- 'accepts tokens minted by this sandbox\'s createCustomToken or client getIdToken(). ' +
30
- `Token must begin with "${SANDBOX_TOKEN_PREFIX}:" or "sandbox-id-token-".`));
17
+ if (isInvalidTokenArgument)
18
+ throw new FirebaseAuthError('argument-error', NOT_A_STRING);
19
+ }
20
+ /**
21
+ * Verifies an ID token minted by pyric's Auth for `expected.projectId`.
22
+ *
23
+ * A token that is not a string throws `auth/argument-error` synchronously, as
24
+ * firebase-admin's `verifyJWT` does. Every other failure rejects with
25
+ * `auth/argument-error`, or `auth/id-token-expired` for an expired token.
26
+ */
27
+ export function verifySandboxIdToken(idToken, expected) {
28
+ assertIdTokenArgument(idToken);
29
+ const nowSec = Math.floor(expected.nowMs / 1000);
30
+ return checkClientIdToken(idToken, expected.projectId, nowSec).then((verdict) => {
31
+ if (!verdict.ok)
32
+ throw new FirebaseAuthError(verdict.code, verdict.message);
33
+ return verdict.token;
34
+ });
35
+ }
36
+ /**
37
+ * firebase-admin's answer for a uid that is not a non-empty string of at most
38
+ * 128 characters (13.10.0 `validator.isUid`), checked before any request.
39
+ */
40
+ export function invalidUid(uid) {
41
+ const isUid = typeof uid === 'string' && uid.length > 0 && uid.length <= 128;
42
+ if (isUid)
43
+ return null;
44
+ return new FirebaseAuthError('invalid-uid', 'The uid must be a non-empty string with at most 128 characters.');
45
+ }
46
+ /** firebase-admin's `getUser` answer for a uid with no record. */
47
+ export function userNotFound() {
48
+ return new FirebaseAuthError('user-not-found', 'There is no user record corresponding to the provided identifier.');
49
+ }
50
+ /**
51
+ * firebase-admin's `verifyDecodedJWTNotRevokedOrDisabled` (13.10.0
52
+ * `lib/auth/base-auth.js`), the `checkRevoked` step: the account must exist,
53
+ * be enabled, and have no revocation after the token's `auth_time`, compared
54
+ * in whole seconds as production stores it.
55
+ */
56
+ export function assertNotRevokedOrDisabled(decoded, standing) {
57
+ const hasNoRecord = standing.kind === 'deleted' || standing.kind === 'unrecorded';
58
+ if (hasNoRecord)
59
+ throw userNotFound();
60
+ if (standing.kind === 'disabled')
61
+ throw new FirebaseAuthError('user-disabled', 'The user record is disabled.');
62
+ const validAfterMs = standing.tokensValidAfterMs;
63
+ const revoked = validAfterMs !== null && decoded.auth_time * 1000 < validAfterMs;
64
+ if (revoked)
65
+ throw new FirebaseAuthError('id-token-revoked', 'The Firebase ID token has been revoked.');
66
+ return decoded;
31
67
  }
32
68
  //# sourceMappingURL=verify-token.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify-token.js","sourceRoot":"","sources":["../../src/auth/verify-token.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE3E;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,MAAM,sBAAsB,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC;IAC3D,IAAI,sBAAsB,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CAAC,4DAA4D,CAAC,CACxE,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC7C,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;QACrC,MAAM,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAChE,IAAI,oBAAoB,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CACP,8DAA8D;QAC5D,qFAAqF;QACrF,0BAA0B,oBAAoB,4BAA4B,CAC7E,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"verify-token.js","sourceRoot":"","sources":["../../src/auth/verify-token.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAA2B,MAAM,qBAAqB,CAAC;AAKlF,sFAAsF;AACtF,MAAM,OAAO,iBAAkB,SAAQ,qBAAqB;IAC1D,YAAY,IAA6C,EAAE,OAAe;QACxE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC/B,CAAC;CACF;AAUD,MAAM,YAAY,GAAG,uEAAuE,CAAC;AAE7F;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,MAAM,sBAAsB,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC;IAC3D,IAAI,sBAAsB;QAAE,MAAM,IAAI,iBAAiB,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;AAC1F,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,QAA4B;IAChF,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACjD,OAAO,kBAAkB,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9E,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,MAAM,IAAI,iBAAiB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5E,OAAO,OAAO,CAAC,KAAK,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC;IAC7E,IAAI,KAAK;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,IAAI,iBAAiB,CAAC,aAAa,EAAE,iEAAiE,CAAC,CAAC;AACjH,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,iBAAiB,CAAC,gBAAgB,EAAE,mEAAmE,CAAC,CAAC;AACtH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAuB,EAAE,QAA6B;IAC/F,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC;IAClF,IAAI,WAAW;QAAE,MAAM,YAAY,EAAE,CAAC;IACtC,IAAI,QAAQ,CAAC,IAAI,KAAK,UAAU;QAAE,MAAM,IAAI,iBAAiB,CAAC,eAAe,EAAE,8BAA8B,CAAC,CAAC;IAC/G,MAAM,YAAY,GAAG,QAAQ,CAAC,kBAAkB,CAAC;IACjD,MAAM,OAAO,GAAG,YAAY,KAAK,IAAI,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,GAAG,YAAY,CAAC;IACjF,IAAI,OAAO;QAAE,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,EAAE,yCAAyC,CAAC,CAAC;IACxG,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pyric-admin",
3
- "version": "0.1.0-alpha.32",
3
+ "version": "0.1.0-alpha.34",
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.32"
109
+ "pyric": "^0.1.0-alpha.34"
110
110
  },
111
111
  "devDependencies": {
112
112
  "@types/bun": "1.3.14",