firebase-functions 6.5.0 → 7.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/lib/_virtual/rolldown_runtime.js +34 -0
  2. package/lib/bin/firebase-functions.js +78 -103
  3. package/lib/common/app.js +35 -55
  4. package/lib/common/change.js +54 -75
  5. package/lib/common/config.js +41 -41
  6. package/lib/common/debug.js +23 -47
  7. package/lib/common/encoding.js +59 -82
  8. package/lib/common/onInit.js +26 -28
  9. package/lib/common/options.js +22 -42
  10. package/lib/common/params.d.ts +6 -6
  11. package/lib/common/params.js +0 -23
  12. package/lib/common/providers/database.js +270 -300
  13. package/lib/common/providers/firestore.js +66 -92
  14. package/lib/common/providers/https.d.ts +0 -1
  15. package/lib/common/providers/https.js +537 -539
  16. package/lib/common/providers/identity.js +393 -444
  17. package/lib/common/providers/tasks.js +64 -98
  18. package/lib/common/timezone.js +544 -542
  19. package/lib/common/trace.d.ts +0 -1
  20. package/lib/common/trace.js +63 -55
  21. package/lib/common/utilities/assertions.d.ts +11 -0
  22. package/lib/common/utilities/assertions.js +18 -0
  23. package/lib/common/utilities/encoder.js +20 -37
  24. package/lib/common/utilities/path-pattern.js +106 -132
  25. package/lib/common/utilities/path.js +28 -27
  26. package/lib/common/utilities/utils.js +23 -45
  27. package/lib/esm/_virtual/rolldown_runtime.mjs +16 -0
  28. package/lib/esm/bin/firebase-functions.mjs +91 -0
  29. package/lib/esm/common/app.mjs +39 -0
  30. package/lib/esm/common/change.mjs +57 -0
  31. package/lib/esm/common/config.mjs +45 -0
  32. package/lib/esm/common/debug.mjs +28 -0
  33. package/lib/esm/common/encoding.mjs +69 -0
  34. package/lib/esm/common/onInit.mjs +33 -0
  35. package/lib/esm/common/options.mjs +22 -0
  36. package/lib/esm/common/params.mjs +1 -0
  37. package/lib/esm/common/providers/database.mjs +269 -0
  38. package/lib/esm/common/providers/firestore.mjs +78 -0
  39. package/lib/esm/common/providers/https.mjs +573 -0
  40. package/lib/esm/common/providers/identity.mjs +428 -0
  41. package/lib/esm/common/providers/tasks.mjs +67 -0
  42. package/lib/esm/common/timezone.mjs +544 -0
  43. package/lib/esm/common/trace.mjs +73 -0
  44. package/lib/esm/common/utilities/assertions.mjs +17 -0
  45. package/lib/esm/common/utilities/encoder.mjs +21 -0
  46. package/lib/esm/common/utilities/path-pattern.mjs +116 -0
  47. package/lib/esm/common/utilities/path.mjs +35 -0
  48. package/lib/esm/common/utilities/utils.mjs +29 -0
  49. package/lib/esm/function-configuration.mjs +1 -0
  50. package/lib/esm/logger/common.mjs +23 -0
  51. package/lib/esm/logger/compat.mjs +25 -0
  52. package/lib/esm/logger/index.mjs +131 -0
  53. package/lib/esm/params/index.mjs +160 -0
  54. package/lib/esm/params/types.mjs +400 -0
  55. package/lib/esm/runtime/loader.mjs +132 -0
  56. package/lib/esm/runtime/manifest.mjs +134 -0
  57. package/lib/esm/types/global.d.mjs +1 -0
  58. package/lib/esm/v1/cloud-functions.mjs +206 -0
  59. package/lib/esm/v1/config.mjs +14 -0
  60. package/lib/esm/v1/function-builder.mjs +252 -0
  61. package/lib/esm/v1/function-configuration.mjs +72 -0
  62. package/lib/esm/v1/index.mjs +27 -0
  63. package/lib/esm/v1/providers/analytics.mjs +212 -0
  64. package/lib/esm/v1/providers/auth.mjs +156 -0
  65. package/lib/esm/v1/providers/database.mjs +243 -0
  66. package/lib/esm/v1/providers/firestore.mjs +131 -0
  67. package/lib/esm/v1/providers/https.mjs +82 -0
  68. package/lib/esm/v1/providers/pubsub.mjs +175 -0
  69. package/lib/esm/v1/providers/remoteConfig.mjs +64 -0
  70. package/lib/esm/v1/providers/storage.mjs +163 -0
  71. package/lib/esm/v1/providers/tasks.mjs +63 -0
  72. package/lib/esm/v1/providers/testLab.mjs +94 -0
  73. package/lib/esm/v2/core.mjs +4 -0
  74. package/lib/esm/v2/index.mjs +28 -0
  75. package/lib/esm/v2/options.mjs +102 -0
  76. package/lib/esm/v2/providers/alerts/alerts.mjs +85 -0
  77. package/lib/esm/v2/providers/alerts/appDistribution.mjs +75 -0
  78. package/lib/esm/v2/providers/alerts/billing.mjs +51 -0
  79. package/lib/esm/v2/providers/alerts/crashlytics.mjs +122 -0
  80. package/lib/esm/v2/providers/alerts/index.mjs +22 -0
  81. package/lib/esm/v2/providers/alerts/performance.mjs +66 -0
  82. package/lib/esm/v2/providers/database.mjs +197 -0
  83. package/lib/esm/v2/providers/dataconnect.mjs +130 -0
  84. package/lib/esm/v2/providers/eventarc.mjs +51 -0
  85. package/lib/esm/v2/providers/firestore.mjs +294 -0
  86. package/lib/esm/v2/providers/https.mjs +210 -0
  87. package/lib/esm/v2/providers/identity.mjs +103 -0
  88. package/lib/esm/v2/providers/pubsub.mjs +148 -0
  89. package/lib/esm/v2/providers/remoteConfig.mjs +52 -0
  90. package/lib/esm/v2/providers/scheduler.mjs +84 -0
  91. package/lib/esm/v2/providers/storage.mjs +155 -0
  92. package/lib/esm/v2/providers/tasks.mjs +65 -0
  93. package/lib/esm/v2/providers/testLab.mjs +53 -0
  94. package/lib/esm/v2/trace.mjs +20 -0
  95. package/lib/function-configuration.d.ts +0 -0
  96. package/lib/function-configuration.js +0 -0
  97. package/lib/logger/common.js +21 -41
  98. package/lib/logger/compat.js +18 -33
  99. package/lib/logger/index.js +119 -130
  100. package/lib/params/index.d.ts +19 -4
  101. package/lib/params/index.js +153 -129
  102. package/lib/params/types.d.ts +17 -0
  103. package/lib/params/types.js +390 -382
  104. package/lib/runtime/loader.js +114 -148
  105. package/lib/runtime/manifest.js +106 -126
  106. package/lib/types/global.d.js +0 -0
  107. package/lib/v1/cloud-functions.d.ts +2 -2
  108. package/lib/v1/cloud-functions.js +193 -241
  109. package/lib/v1/config.d.ts +4 -7
  110. package/lib/v1/config.js +13 -75
  111. package/lib/v1/function-builder.js +239 -368
  112. package/lib/v1/function-configuration.js +70 -63
  113. package/lib/v1/index.js +118 -73
  114. package/lib/v1/providers/analytics.js +189 -210
  115. package/lib/v1/providers/auth.d.ts +2 -1
  116. package/lib/v1/providers/auth.js +159 -164
  117. package/lib/v1/providers/database.js +237 -242
  118. package/lib/v1/providers/firestore.js +131 -130
  119. package/lib/v1/providers/https.d.ts +2 -1
  120. package/lib/v1/providers/https.js +79 -86
  121. package/lib/v1/providers/pubsub.js +175 -172
  122. package/lib/v1/providers/remoteConfig.js +64 -68
  123. package/lib/v1/providers/storage.js +161 -163
  124. package/lib/v1/providers/tasks.d.ts +1 -1
  125. package/lib/v1/providers/tasks.js +65 -80
  126. package/lib/v1/providers/testLab.js +94 -94
  127. package/lib/v2/core.d.ts +1 -1
  128. package/lib/v2/core.js +5 -32
  129. package/lib/v2/index.d.ts +6 -3
  130. package/lib/v2/index.js +123 -75
  131. package/lib/v2/options.js +88 -114
  132. package/lib/v2/providers/alerts/alerts.js +76 -95
  133. package/lib/v2/providers/alerts/appDistribution.js +73 -78
  134. package/lib/v2/providers/alerts/billing.js +49 -53
  135. package/lib/v2/providers/alerts/crashlytics.js +110 -102
  136. package/lib/v2/providers/alerts/index.js +56 -53
  137. package/lib/v2/providers/alerts/performance.js +64 -74
  138. package/lib/v2/providers/database.js +177 -180
  139. package/lib/v2/providers/dataconnect.d.ts +95 -0
  140. package/lib/v2/providers/dataconnect.js +137 -0
  141. package/lib/v2/providers/eventarc.js +55 -77
  142. package/lib/v2/providers/firestore.js +262 -260
  143. package/lib/v2/providers/https.d.ts +3 -2
  144. package/lib/v2/providers/https.js +210 -247
  145. package/lib/v2/providers/identity.d.ts +2 -1
  146. package/lib/v2/providers/identity.js +96 -105
  147. package/lib/v2/providers/pubsub.js +149 -167
  148. package/lib/v2/providers/remoteConfig.js +54 -63
  149. package/lib/v2/providers/scheduler.js +84 -96
  150. package/lib/v2/providers/storage.js +147 -162
  151. package/lib/v2/providers/tasks.d.ts +1 -1
  152. package/lib/v2/providers/tasks.js +68 -95
  153. package/lib/v2/providers/testLab.js +55 -64
  154. package/lib/v2/trace.js +18 -19
  155. package/package.json +290 -226
  156. package/protos/compiledFirestore.mjs +3512 -0
  157. package/protos/update.sh +28 -7
@@ -0,0 +1,428 @@
1
+ import { debug, error, warn } from "../../logger/index.mjs";
2
+ import { getApp } from "../app.mjs";
3
+ import { isDebugFeatureEnabled } from "../debug.mjs";
4
+ import { HttpsError, unsafeDecodeToken } from "./https.mjs";
5
+ import * as auth from "firebase-admin/auth";
6
+
7
+ //#region src/common/providers/identity.ts
8
+ const DISALLOWED_CUSTOM_CLAIMS = [
9
+ "acr",
10
+ "amr",
11
+ "at_hash",
12
+ "aud",
13
+ "auth_time",
14
+ "azp",
15
+ "cnf",
16
+ "c_hash",
17
+ "exp",
18
+ "iat",
19
+ "iss",
20
+ "jti",
21
+ "nbf",
22
+ "nonce",
23
+ "firebase"
24
+ ];
25
+ const CLAIMS_MAX_PAYLOAD_SIZE = 1e3;
26
+ const EVENT_MAPPING = {
27
+ beforeCreate: "providers/cloud.auth/eventTypes/user.beforeCreate",
28
+ beforeSignIn: "providers/cloud.auth/eventTypes/user.beforeSignIn",
29
+ beforeSendEmail: "providers/cloud.auth/eventTypes/user.beforeSendEmail",
30
+ beforeSendSms: "providers/cloud.auth/eventTypes/user.beforeSendSms"
31
+ };
32
+ /**
33
+ * Helper class to create the user metadata in a `UserRecord` object.
34
+ */
35
+ var UserRecordMetadata = class {
36
+ constructor(creationTime, lastSignInTime) {
37
+ this.creationTime = creationTime;
38
+ this.lastSignInTime = lastSignInTime;
39
+ }
40
+ /** Returns a plain JavaScript object with the properties of UserRecordMetadata. */
41
+ toJSON() {
42
+ return {
43
+ creationTime: this.creationTime,
44
+ lastSignInTime: this.lastSignInTime
45
+ };
46
+ }
47
+ };
48
+ /**
49
+ * Helper function that creates a `UserRecord` class from data sent over the wire.
50
+ * @param wireData data sent over the wire
51
+ * @returns an instance of `UserRecord` with correct toJSON functions
52
+ */
53
+ function userRecordConstructor(wireData) {
54
+ const falseyValues = {
55
+ email: null,
56
+ emailVerified: false,
57
+ displayName: null,
58
+ photoURL: null,
59
+ phoneNumber: null,
60
+ disabled: false,
61
+ providerData: [],
62
+ customClaims: {},
63
+ passwordSalt: null,
64
+ passwordHash: null,
65
+ tokensValidAfterTime: null
66
+ };
67
+ const record = {
68
+ ...falseyValues,
69
+ ...wireData
70
+ };
71
+ const meta = record.metadata;
72
+ if (meta) {
73
+ record.metadata = new UserRecordMetadata(meta.createdAt || meta.creationTime, meta.lastSignedInAt || meta.lastSignInTime);
74
+ } else {
75
+ record.metadata = new UserRecordMetadata(null, null);
76
+ }
77
+ record.toJSON = () => {
78
+ const { uid, email, emailVerified, displayName, photoURL, phoneNumber, disabled, passwordHash, passwordSalt, tokensValidAfterTime } = record;
79
+ const json = {
80
+ uid,
81
+ email,
82
+ emailVerified,
83
+ displayName,
84
+ photoURL,
85
+ phoneNumber,
86
+ disabled,
87
+ passwordHash,
88
+ passwordSalt,
89
+ tokensValidAfterTime
90
+ };
91
+ json.metadata = record.metadata.toJSON();
92
+ json.customClaims = JSON.parse(JSON.stringify(record.customClaims));
93
+ json.providerData = record.providerData.map((entry) => {
94
+ const newEntry = { ...entry };
95
+ newEntry.toJSON = () => entry;
96
+ return newEntry;
97
+ });
98
+ return json;
99
+ };
100
+ return record;
101
+ }
102
+ /**
103
+ * Checks for a valid identity platform web request, otherwise throws an HttpsError.
104
+ * @internal
105
+ */
106
+ function isValidRequest(req) {
107
+ if (req.method !== "POST") {
108
+ warn(`Request has invalid method "${req.method}".`);
109
+ return false;
110
+ }
111
+ const contentType = (req.header("Content-Type") || "").toLowerCase();
112
+ if (!contentType.includes("application/json")) {
113
+ warn("Request has invalid header Content-Type.");
114
+ return false;
115
+ }
116
+ if (!req.body?.data?.jwt) {
117
+ warn("Request has an invalid body.");
118
+ return false;
119
+ }
120
+ return true;
121
+ }
122
+ /**
123
+ * Decode, but not verify, an Auth Blocking token.
124
+ *
125
+ * Do not use in production. Token should always be verified using the Admin SDK.
126
+ *
127
+ * This is exposed only for testing.
128
+ */
129
+ function unsafeDecodeAuthBlockingToken(token) {
130
+ const decoded = unsafeDecodeToken(token);
131
+ decoded.uid = decoded.sub;
132
+ return decoded;
133
+ }
134
+ /**
135
+ * Helper function to parse the decoded metadata object into a `UserMetaData` object
136
+ * @internal
137
+ */
138
+ function parseMetadata(metadata) {
139
+ const creationTime = metadata?.creation_time ? new Date(metadata.creation_time).toUTCString() : null;
140
+ const lastSignInTime = metadata?.last_sign_in_time ? new Date(metadata.last_sign_in_time).toUTCString() : null;
141
+ return {
142
+ creationTime,
143
+ lastSignInTime
144
+ };
145
+ }
146
+ /**
147
+ * Helper function to parse the decoded user info array into an `AuthUserInfo` array.
148
+ * @internal
149
+ */
150
+ function parseProviderData(providerData) {
151
+ const providers = [];
152
+ for (const provider of providerData) {
153
+ providers.push({
154
+ uid: provider.uid,
155
+ displayName: provider.display_name,
156
+ email: provider.email,
157
+ photoURL: provider.photo_url,
158
+ providerId: provider.provider_id,
159
+ phoneNumber: provider.phone_number
160
+ });
161
+ }
162
+ return providers;
163
+ }
164
+ /**
165
+ * Helper function to parse the date into a UTC string.
166
+ * @internal
167
+ */
168
+ function parseDate(tokensValidAfterTime) {
169
+ if (!tokensValidAfterTime) {
170
+ return null;
171
+ }
172
+ tokensValidAfterTime = tokensValidAfterTime * 1e3;
173
+ try {
174
+ const date = new Date(tokensValidAfterTime);
175
+ if (!isNaN(date.getTime())) {
176
+ return date.toUTCString();
177
+ }
178
+ } catch {}
179
+ return null;
180
+ }
181
+ /**
182
+ * Helper function to parse the decoded enrolled factors into a valid MultiFactorSettings
183
+ * @internal
184
+ */
185
+ function parseMultiFactor(multiFactor) {
186
+ if (!multiFactor) {
187
+ return null;
188
+ }
189
+ const parsedEnrolledFactors = [];
190
+ for (const factor of multiFactor.enrolled_factors || []) {
191
+ if (!factor.uid) {
192
+ throw new HttpsError("internal", "INTERNAL ASSERT FAILED: Invalid multi-factor info response");
193
+ }
194
+ const enrollmentTime = factor.enrollment_time ? new Date(factor.enrollment_time).toUTCString() : null;
195
+ parsedEnrolledFactors.push({
196
+ uid: factor.uid,
197
+ factorId: factor.phone_number ? factor.factor_id || "phone" : factor.factor_id,
198
+ displayName: factor.display_name,
199
+ enrollmentTime,
200
+ phoneNumber: factor.phone_number
201
+ });
202
+ }
203
+ if (parsedEnrolledFactors.length > 0) {
204
+ return { enrolledFactors: parsedEnrolledFactors };
205
+ }
206
+ return null;
207
+ }
208
+ /**
209
+ * Parses the decoded user record into a valid UserRecord for use in the handler
210
+ * @internal
211
+ */
212
+ function parseAuthUserRecord(decodedJWTUserRecord) {
213
+ if (!decodedJWTUserRecord.uid) {
214
+ throw new HttpsError("internal", "INTERNAL ASSERT FAILED: Invalid user response");
215
+ }
216
+ const disabled = decodedJWTUserRecord.disabled || false;
217
+ const metadata = parseMetadata(decodedJWTUserRecord.metadata);
218
+ const providerData = parseProviderData(decodedJWTUserRecord.provider_data);
219
+ const tokensValidAfterTime = parseDate(decodedJWTUserRecord.tokens_valid_after_time);
220
+ const multiFactor = parseMultiFactor(decodedJWTUserRecord.multi_factor);
221
+ return {
222
+ uid: decodedJWTUserRecord.uid,
223
+ email: decodedJWTUserRecord.email,
224
+ emailVerified: decodedJWTUserRecord.email_verified,
225
+ displayName: decodedJWTUserRecord.display_name,
226
+ photoURL: decodedJWTUserRecord.photo_url,
227
+ phoneNumber: decodedJWTUserRecord.phone_number,
228
+ disabled,
229
+ metadata,
230
+ providerData,
231
+ passwordHash: decodedJWTUserRecord.password_hash,
232
+ passwordSalt: decodedJWTUserRecord.password_salt,
233
+ customClaims: decodedJWTUserRecord.custom_claims,
234
+ tenantId: decodedJWTUserRecord.tenant_id,
235
+ tokensValidAfterTime,
236
+ multiFactor
237
+ };
238
+ }
239
+ /** Helper to get the `AdditionalUserInfo` from the decoded JWT */
240
+ function parseAdditionalUserInfo(decodedJWT) {
241
+ let profile;
242
+ let username;
243
+ if (decodedJWT.raw_user_info) {
244
+ try {
245
+ profile = JSON.parse(decodedJWT.raw_user_info);
246
+ } catch (err) {
247
+ debug(`Parse Error: ${err.message}`);
248
+ }
249
+ }
250
+ if (profile) {
251
+ if (decodedJWT.sign_in_method === "github.com") {
252
+ username = profile.login;
253
+ }
254
+ if (decodedJWT.sign_in_method === "twitter.com") {
255
+ username = profile.screen_name;
256
+ }
257
+ }
258
+ return {
259
+ providerId: decodedJWT.sign_in_method === "emailLink" ? "password" : decodedJWT.sign_in_method,
260
+ profile,
261
+ username,
262
+ isNewUser: decodedJWT.event_type === "beforeCreate" ? true : false,
263
+ recaptchaScore: decodedJWT.recaptcha_score,
264
+ email: decodedJWT.email,
265
+ phoneNumber: decodedJWT.phone_number
266
+ };
267
+ }
268
+ /**
269
+ * Helper to generate a response from the blocking function to the Firebase Auth backend.
270
+ * @internal
271
+ */
272
+ function generateResponsePayload(authResponse) {
273
+ if (!authResponse) {
274
+ return {};
275
+ }
276
+ const { recaptchaActionOverride,...formattedAuthResponse } = authResponse;
277
+ const result = {};
278
+ const updateMask = getUpdateMask(formattedAuthResponse);
279
+ if (updateMask.length !== 0) {
280
+ result.userRecord = {
281
+ ...formattedAuthResponse,
282
+ updateMask
283
+ };
284
+ }
285
+ if (recaptchaActionOverride !== undefined) {
286
+ result.recaptchaActionOverride = recaptchaActionOverride;
287
+ }
288
+ return result;
289
+ }
290
+ /** Helper to get the Credential from the decoded JWT */
291
+ function parseAuthCredential(decodedJWT, time) {
292
+ if (!decodedJWT.sign_in_attributes && !decodedJWT.oauth_id_token && !decodedJWT.oauth_access_token && !decodedJWT.oauth_refresh_token) {
293
+ return null;
294
+ }
295
+ return {
296
+ claims: decodedJWT.sign_in_attributes,
297
+ idToken: decodedJWT.oauth_id_token,
298
+ accessToken: decodedJWT.oauth_access_token,
299
+ refreshToken: decodedJWT.oauth_refresh_token,
300
+ expirationTime: decodedJWT.oauth_expires_in ? new Date(time + decodedJWT.oauth_expires_in * 1e3).toUTCString() : undefined,
301
+ secret: decodedJWT.oauth_token_secret,
302
+ providerId: decodedJWT.sign_in_method === "emailLink" ? "password" : decodedJWT.sign_in_method,
303
+ signInMethod: decodedJWT.sign_in_method
304
+ };
305
+ }
306
+ /**
307
+ * Parses the decoded jwt into a valid AuthEventContext for use in the handler
308
+ * @internal
309
+ */
310
+ function parseAuthEventContext(decodedJWT, projectId, time = new Date().getTime()) {
311
+ const eventType = (EVENT_MAPPING[decodedJWT.event_type] || decodedJWT.event_type) + (decodedJWT.sign_in_method ? `:${decodedJWT.sign_in_method}` : "");
312
+ return {
313
+ locale: decodedJWT.locale,
314
+ ipAddress: decodedJWT.ip_address,
315
+ userAgent: decodedJWT.user_agent,
316
+ eventId: decodedJWT.event_id,
317
+ eventType,
318
+ authType: decodedJWT.user_record ? "USER" : "UNAUTHENTICATED",
319
+ resource: {
320
+ service: "identitytoolkit.googleapis.com",
321
+ name: decodedJWT.tenant_id ? `projects/${projectId}/tenants/${decodedJWT.tenant_id}` : `projects/${projectId}`
322
+ },
323
+ timestamp: new Date(decodedJWT.iat * 1e3).toUTCString(),
324
+ additionalUserInfo: parseAdditionalUserInfo(decodedJWT),
325
+ credential: parseAuthCredential(decodedJWT, time),
326
+ emailType: decodedJWT.email_type,
327
+ smsType: decodedJWT.sms_type,
328
+ params: {}
329
+ };
330
+ }
331
+ /**
332
+ * Checks the handler response for invalid customClaims & sessionClaims objects
333
+ * @internal
334
+ */
335
+ function validateAuthResponse(eventType, authRequest) {
336
+ if (!authRequest) {
337
+ authRequest = {};
338
+ }
339
+ if (authRequest.customClaims) {
340
+ const invalidClaims = DISALLOWED_CUSTOM_CLAIMS.filter((claim) => authRequest.customClaims.hasOwnProperty(claim));
341
+ if (invalidClaims.length > 0) {
342
+ throw new HttpsError("invalid-argument", `The customClaims claims "${invalidClaims.join(",")}" are reserved and cannot be specified.`);
343
+ }
344
+ if (JSON.stringify(authRequest.customClaims).length > CLAIMS_MAX_PAYLOAD_SIZE) {
345
+ throw new HttpsError("invalid-argument", `The customClaims payload should not exceed ${CLAIMS_MAX_PAYLOAD_SIZE} characters.`);
346
+ }
347
+ }
348
+ if (eventType === "beforeSignIn" && authRequest.sessionClaims) {
349
+ const invalidClaims = DISALLOWED_CUSTOM_CLAIMS.filter((claim) => authRequest.sessionClaims.hasOwnProperty(claim));
350
+ if (invalidClaims.length > 0) {
351
+ throw new HttpsError("invalid-argument", `The sessionClaims claims "${invalidClaims.join(",")}" are reserved and cannot be specified.`);
352
+ }
353
+ if (JSON.stringify(authRequest.sessionClaims).length > CLAIMS_MAX_PAYLOAD_SIZE) {
354
+ throw new HttpsError("invalid-argument", `The sessionClaims payload should not exceed ${CLAIMS_MAX_PAYLOAD_SIZE} characters.`);
355
+ }
356
+ const combinedClaims = {
357
+ ...authRequest.customClaims,
358
+ ...authRequest.sessionClaims
359
+ };
360
+ if (JSON.stringify(combinedClaims).length > CLAIMS_MAX_PAYLOAD_SIZE) {
361
+ throw new HttpsError("invalid-argument", `The customClaims and sessionClaims payloads should not exceed ${CLAIMS_MAX_PAYLOAD_SIZE} characters combined.`);
362
+ }
363
+ }
364
+ }
365
+ /**
366
+ * Helper function to generate the update mask for the identity platform changed values
367
+ * @internal
368
+ */
369
+ function getUpdateMask(authResponse) {
370
+ if (!authResponse) {
371
+ return "";
372
+ }
373
+ const updateMask = [];
374
+ for (const key in authResponse) {
375
+ if (authResponse.hasOwnProperty(key) && typeof authResponse[key] !== "undefined") {
376
+ updateMask.push(key);
377
+ }
378
+ }
379
+ return updateMask.join(",");
380
+ }
381
+ /** @internal */
382
+ function wrapHandler(eventType, handler) {
383
+ return async (req, res) => {
384
+ try {
385
+ const projectId = process.env.GCLOUD_PROJECT;
386
+ if (!isValidRequest(req)) {
387
+ error("Invalid request, unable to process");
388
+ throw new HttpsError("invalid-argument", "Bad Request");
389
+ }
390
+ if (!auth.getAuth(getApp())._verifyAuthBlockingToken) {
391
+ throw new Error("Cannot validate Auth Blocking token. Please update Firebase Admin SDK to >= v10.1.0");
392
+ }
393
+ const decodedPayload = isDebugFeatureEnabled("skipTokenVerification") ? unsafeDecodeAuthBlockingToken(req.body.data.jwt) : handler.platform === "gcfv1" ? await auth.getAuth(getApp())._verifyAuthBlockingToken(req.body.data.jwt) : await auth.getAuth(getApp())._verifyAuthBlockingToken(req.body.data.jwt, "run.app");
394
+ let authUserRecord;
395
+ if (decodedPayload.event_type === "beforeCreate" || decodedPayload.event_type === "beforeSignIn") {
396
+ authUserRecord = parseAuthUserRecord(decodedPayload.user_record);
397
+ }
398
+ const authEventContext = parseAuthEventContext(decodedPayload, projectId);
399
+ let authResponse;
400
+ if (handler.platform === "gcfv1") {
401
+ authResponse = authUserRecord ? await handler(authUserRecord, authEventContext) || undefined : await handler(authEventContext) || undefined;
402
+ } else {
403
+ authResponse = await handler({
404
+ ...authEventContext,
405
+ data: authUserRecord
406
+ }) || undefined;
407
+ }
408
+ validateAuthResponse(eventType, authResponse);
409
+ const result = generateResponsePayload(authResponse);
410
+ res.status(200);
411
+ res.setHeader("Content-Type", "application/json");
412
+ res.send(JSON.stringify(result));
413
+ } catch (err) {
414
+ let httpErr = err;
415
+ if (!(httpErr instanceof HttpsError)) {
416
+ error("Unhandled error", err);
417
+ httpErr = new HttpsError("internal", "An unexpected error occurred.");
418
+ }
419
+ const { status } = httpErr.httpErrorCode;
420
+ const body = { error: httpErr.toJSON() };
421
+ res.setHeader("Content-Type", "application/json");
422
+ res.status(status).send(body);
423
+ }
424
+ };
425
+ }
426
+
427
+ //#endregion
428
+ export { HttpsError, UserRecordMetadata, generateResponsePayload, getUpdateMask, isValidRequest, parseAuthEventContext, parseAuthUserRecord, parseDate, parseMetadata, parseMultiFactor, parseProviderData, userRecordConstructor, validateAuthResponse, wrapHandler };
@@ -0,0 +1,67 @@
1
+ import { error } from "../../logger/index.mjs";
2
+ import { HttpsError, decode, isValidRequest, unsafeDecodeIdToken } from "./https.mjs";
3
+
4
+ //#region src/common/providers/tasks.ts
5
+ /** @internal */
6
+ function onDispatchHandler(handler) {
7
+ return async (req, res) => {
8
+ try {
9
+ if (!isValidRequest(req)) {
10
+ error("Invalid request, unable to process.");
11
+ throw new HttpsError("invalid-argument", "Bad Request");
12
+ }
13
+ const headers = {};
14
+ for (const [key, value] of Object.entries(req.headers)) {
15
+ if (!Array.isArray(value)) {
16
+ headers[key] = value;
17
+ }
18
+ }
19
+ const context = {
20
+ queueName: req.header("X-CloudTasks-QueueName"),
21
+ id: req.header("X-CloudTasks-TaskName"),
22
+ retryCount: req.header("X-CloudTasks-TaskRetryCount") ? Number(req.header("X-CloudTasks-TaskRetryCount")) : undefined,
23
+ executionCount: req.header("X-CloudTasks-TaskExecutionCount") ? Number(req.header("X-CloudTasks-TaskExecutionCount")) : undefined,
24
+ scheduledTime: req.header("X-CloudTasks-TaskETA"),
25
+ previousResponse: req.header("X-CloudTasks-TaskPreviousResponse") ? Number(req.header("X-CloudTasks-TaskPreviousResponse")) : undefined,
26
+ retryReason: req.header("X-CloudTasks-TaskRetryReason"),
27
+ headers
28
+ };
29
+ if (!process.env.FUNCTIONS_EMULATOR) {
30
+ const authHeader = req.header("Authorization") || "";
31
+ const token = authHeader.match(/^Bearer (.*)$/)?.[1];
32
+ if (!token) {
33
+ throw new HttpsError("unauthenticated", "Unauthenticated");
34
+ }
35
+ const authToken = unsafeDecodeIdToken(token);
36
+ context.auth = {
37
+ uid: authToken.uid,
38
+ token: authToken,
39
+ rawToken: token
40
+ };
41
+ }
42
+ const data = decode(req.body.data);
43
+ if (handler.length === 2) {
44
+ await handler(data, context);
45
+ } else {
46
+ const arg = {
47
+ ...context,
48
+ data
49
+ };
50
+ await handler(arg);
51
+ }
52
+ res.status(204).end();
53
+ } catch (err) {
54
+ let httpErr = err;
55
+ if (!(err instanceof HttpsError)) {
56
+ error("Unhandled error", err);
57
+ httpErr = new HttpsError("internal", "INTERNAL");
58
+ }
59
+ const { status } = httpErr.httpErrorCode;
60
+ const body = { error: httpErr.toJSON() };
61
+ res.status(status).send(body);
62
+ }
63
+ };
64
+ }
65
+
66
+ //#endregion
67
+ export { onDispatchHandler };