strapi-plugin-firebase-authentication 1.2.4 → 1.3.2

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.
@@ -298,6 +298,16 @@ const attributes$1 = {
298
298
  emailVerificationEmailSubject: {
299
299
  type: "string",
300
300
  "default": "Verify Your Email"
301
+ },
302
+ includeCredentialsInPasswordResetLink: {
303
+ type: "boolean",
304
+ "default": false,
305
+ description: "Include Firebase custom token in password reset links for auto-login"
306
+ },
307
+ includeCredentialsInVerificationLink: {
308
+ type: "boolean",
309
+ "default": false,
310
+ description: "Include Firebase custom token in email verification links for auto-login"
301
311
  }
302
312
  };
303
313
  const firebaseAuthenticationConfiguration = {
@@ -28962,6 +28972,29 @@ const firebaseController = {
28962
28972
  }
28963
28973
  throw error2;
28964
28974
  }
28975
+ },
28976
+ /**
28977
+ * Check password - validates a password against the authenticated user's Firebase account
28978
+ * POST /api/firebase-authentication/checkPassword
28979
+ * Authenticated endpoint - requires valid JWT (enforced by is-authenticated policy)
28980
+ *
28981
+ * @param ctx - Koa context with { password } in body
28982
+ * @returns { valid: true } or { valid: false }
28983
+ */
28984
+ async checkPassword(ctx) {
28985
+ strapi.log.debug("checkPassword endpoint called");
28986
+ try {
28987
+ const { password } = ctx.request.body || {};
28988
+ const user = ctx.state.user;
28989
+ if (!password) {
28990
+ throw new ValidationError$1("Password is required");
28991
+ }
28992
+ const result = await strapi.plugin(pluginName).service("firebaseService").checkPassword(user, password);
28993
+ ctx.body = result;
28994
+ } catch (error2) {
28995
+ strapi.log.error("checkPassword controller error:", error2);
28996
+ throw error2;
28997
+ }
28965
28998
  }
28966
28999
  };
28967
29000
  const STRAPI_DESTINATION = "strapi";
@@ -29164,7 +29197,9 @@ const settingsController = {
29164
29197
  magicLinkEmailSubject = "Sign in to Your Application",
29165
29198
  magicLinkExpiryHours = 1,
29166
29199
  emailVerificationUrl = "http://localhost:3000/verify-email",
29167
- emailVerificationEmailSubject = "Verify Your Email"
29200
+ emailVerificationEmailSubject = "Verify Your Email",
29201
+ includeCredentialsInPasswordResetLink = false,
29202
+ includeCredentialsInVerificationLink = false
29168
29203
  } = requestBody;
29169
29204
  const existingConfig = await strapi.db.query("plugin::firebase-authentication.firebase-authentication-configuration").findOne({ where: {} });
29170
29205
  let result;
@@ -29180,7 +29215,9 @@ const settingsController = {
29180
29215
  magicLinkEmailSubject,
29181
29216
  magicLinkExpiryHours,
29182
29217
  emailVerificationUrl,
29183
- emailVerificationEmailSubject
29218
+ emailVerificationEmailSubject,
29219
+ includeCredentialsInPasswordResetLink,
29220
+ includeCredentialsInVerificationLink
29184
29221
  }
29185
29222
  });
29186
29223
  } else {
@@ -29196,7 +29233,9 @@ const settingsController = {
29196
29233
  magicLinkEmailSubject,
29197
29234
  magicLinkExpiryHours,
29198
29235
  emailVerificationUrl,
29199
- emailVerificationEmailSubject
29236
+ emailVerificationEmailSubject,
29237
+ includeCredentialsInPasswordResetLink,
29238
+ includeCredentialsInVerificationLink
29200
29239
  }
29201
29240
  });
29202
29241
  }
@@ -29210,7 +29249,9 @@ const settingsController = {
29210
29249
  magicLinkEmailSubject: result.magicLinkEmailSubject,
29211
29250
  magicLinkExpiryHours: result.magicLinkExpiryHours,
29212
29251
  emailVerificationUrl: result.emailVerificationUrl,
29213
- emailVerificationEmailSubject: result.emailVerificationEmailSubject
29252
+ emailVerificationEmailSubject: result.emailVerificationEmailSubject,
29253
+ includeCredentialsInPasswordResetLink: result.includeCredentialsInPasswordResetLink,
29254
+ includeCredentialsInVerificationLink: result.includeCredentialsInVerificationLink
29214
29255
  };
29215
29256
  } catch (error2) {
29216
29257
  throw new ApplicationError$2("Error saving password configuration", {
@@ -29434,6 +29475,14 @@ const contentApi = {
29434
29475
  // Public endpoint - token provides authentication
29435
29476
  policies: []
29436
29477
  }
29478
+ },
29479
+ {
29480
+ method: "POST",
29481
+ path: "/checkPassword",
29482
+ handler: "firebaseController.checkPassword",
29483
+ config: {
29484
+ policies: ["plugin::firebase-authentication.is-authenticated"]
29485
+ }
29437
29486
  }
29438
29487
  ]
29439
29488
  };
@@ -29557,7 +29606,10 @@ const settingsService = ({ strapi: strapi2 }) => {
29557
29606
  magicLinkExpiryHours: configObject.magicLinkExpiryHours || 1,
29558
29607
  // Include email verification configuration fields
29559
29608
  emailVerificationUrl: configObject.emailVerificationUrl || "http://localhost:3000/verify-email",
29560
- emailVerificationEmailSubject: configObject.emailVerificationEmailSubject || "Verify Your Email"
29609
+ emailVerificationEmailSubject: configObject.emailVerificationEmailSubject || "Verify Your Email",
29610
+ // Include credentials in link settings
29611
+ includeCredentialsInPasswordResetLink: configObject.includeCredentialsInPasswordResetLink || false,
29612
+ includeCredentialsInVerificationLink: configObject.includeCredentialsInVerificationLink || false
29561
29613
  };
29562
29614
  } catch (error2) {
29563
29615
  strapi2.log.error(`Firebase config error: ${error2.message}`);
@@ -29602,7 +29654,9 @@ const settingsService = ({ strapi: strapi2 }) => {
29602
29654
  magicLinkEmailSubject = "Sign in to Your Application",
29603
29655
  magicLinkExpiryHours = 1,
29604
29656
  emailVerificationUrl = "http://localhost:3000/verify-email",
29605
- emailVerificationEmailSubject = "Verify Your Email"
29657
+ emailVerificationEmailSubject = "Verify Your Email",
29658
+ includeCredentialsInPasswordResetLink = false,
29659
+ includeCredentialsInVerificationLink = false
29606
29660
  } = requestBody;
29607
29661
  if (!requestBody) throw new ValidationError3(ERROR_MESSAGES.MISSING_DATA);
29608
29662
  try {
@@ -29640,7 +29694,9 @@ const settingsService = ({ strapi: strapi2 }) => {
29640
29694
  magicLinkEmailSubject,
29641
29695
  magicLinkExpiryHours,
29642
29696
  emailVerificationUrl,
29643
- emailVerificationEmailSubject
29697
+ emailVerificationEmailSubject,
29698
+ includeCredentialsInPasswordResetLink,
29699
+ includeCredentialsInVerificationLink
29644
29700
  }
29645
29701
  });
29646
29702
  } else {
@@ -29658,7 +29714,9 @@ const settingsService = ({ strapi: strapi2 }) => {
29658
29714
  magicLinkEmailSubject,
29659
29715
  magicLinkExpiryHours,
29660
29716
  emailVerificationUrl,
29661
- emailVerificationEmailSubject
29717
+ emailVerificationEmailSubject,
29718
+ includeCredentialsInPasswordResetLink,
29719
+ includeCredentialsInVerificationLink
29662
29720
  }
29663
29721
  });
29664
29722
  }
@@ -29695,6 +29753,8 @@ const settingsService = ({ strapi: strapi2 }) => {
29695
29753
  res.magicLinkExpiryHours = res.magicLinkExpiryHours || magicLinkExpiryHours;
29696
29754
  res.emailVerificationUrl = res.emailVerificationUrl || emailVerificationUrl;
29697
29755
  res.emailVerificationEmailSubject = res.emailVerificationEmailSubject || emailVerificationEmailSubject;
29756
+ res.includeCredentialsInPasswordResetLink = res.includeCredentialsInPasswordResetLink ?? includeCredentialsInPasswordResetLink;
29757
+ res.includeCredentialsInVerificationLink = res.includeCredentialsInVerificationLink ?? includeCredentialsInVerificationLink;
29698
29758
  return res;
29699
29759
  } catch (error2) {
29700
29760
  strapi2.log.error("=== FIREBASE CONFIG SAVE ERROR ===");
@@ -30895,7 +30955,16 @@ const firebaseService = ({ strapi: strapi2 }) => ({
30895
30955
  );
30896
30956
  const tokenService2 = strapi2.plugin("firebase-authentication").service("tokenService");
30897
30957
  const token = await tokenService2.generateResetToken(firebaseData.documentId);
30898
- const resetLink = `${resetUrl}?token=${token}`;
30958
+ let resetLink = `${resetUrl}?token=${token}`;
30959
+ if (config2?.includeCredentialsInPasswordResetLink) {
30960
+ try {
30961
+ const customToken = await strapi2.firebase.auth().createCustomToken(firebaseUser.uid);
30962
+ resetLink = `${resetLink}&fjwt=${customToken}`;
30963
+ strapi2.log.info(`[forgotPassword] Added Firebase custom token to reset link`);
30964
+ } catch (tokenError) {
30965
+ strapi2.log.warn(`[forgotPassword] Could not generate custom token: ${tokenError.message}`);
30966
+ }
30967
+ }
30899
30968
  strapi2.log.info(`✅ [forgotPassword] Custom reset link generated for ${email2}`);
30900
30969
  strapi2.log.info(`[forgotPassword] Attempting to send password reset email to: ${email2}`);
30901
30970
  await strapi2.plugin("firebase-authentication").service("emailService").sendPasswordResetEmail(firebaseUser, resetLink);
@@ -31120,7 +31189,16 @@ const firebaseService = ({ strapi: strapi2 }) => ({
31120
31189
  );
31121
31190
  const tokenService2 = strapi2.plugin("firebase-authentication").service("tokenService");
31122
31191
  const token = await tokenService2.generateVerificationToken(firebaseData.documentId, email2);
31123
- const verificationLink = `${verificationUrl}?token=${token}`;
31192
+ let verificationLink = `${verificationUrl}?token=${token}`;
31193
+ if (config2?.includeCredentialsInVerificationLink) {
31194
+ try {
31195
+ const customToken = await strapi2.firebase.auth().createCustomToken(firebaseUser.uid);
31196
+ verificationLink = `${verificationLink}&fjwt=${customToken}`;
31197
+ strapi2.log.info(`[sendVerificationEmail] Added Firebase custom token to verification link`);
31198
+ } catch (tokenError) {
31199
+ strapi2.log.warn(`[sendVerificationEmail] Could not generate custom token: ${tokenError.message}`);
31200
+ }
31201
+ }
31124
31202
  strapi2.log.info(`✅ [sendVerificationEmail] Verification link generated for ${email2}`);
31125
31203
  strapi2.log.info(`[sendVerificationEmail] Attempting to send verification email to: ${email2}`);
31126
31204
  await strapi2.plugin("firebase-authentication").service("emailService").sendVerificationEmail(firebaseUser, verificationLink);
@@ -31232,6 +31310,54 @@ const firebaseService = ({ strapi: strapi2 }) => ({
31232
31310
  }
31233
31311
  throw new ApplicationError$2("Failed to verify email. Please try again.");
31234
31312
  }
31313
+ },
31314
+ /**
31315
+ * Check if a password is valid for the authenticated user
31316
+ * Uses Firebase Identity Toolkit API to verify the password
31317
+ *
31318
+ * @param user - Authenticated user from ctx.state.user
31319
+ * @param password - Password to check
31320
+ * @returns { valid: true } or { valid: false }
31321
+ */
31322
+ async checkPassword(user, password) {
31323
+ if (!user || !user.email) {
31324
+ throw new ValidationError$1("User email is required");
31325
+ }
31326
+ const config2 = await strapi2.plugin("firebase-authentication").service("settingsService").getFirebaseConfigJson();
31327
+ if (!config2 || !config2.firebaseWebApiKey) {
31328
+ throw new ApplicationError$2(
31329
+ "Password verification is not available. Web API Key is not configured.\n\nTo enable password verification:\n1. Go to Firebase Console > Project Settings > General\n2. Copy your Web API Key\n3. Add it in Strapi Admin > Settings > Firebase Authentication > Optional Settings"
31330
+ );
31331
+ }
31332
+ try {
31333
+ const response = await fetch(
31334
+ `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${config2.firebaseWebApiKey}`,
31335
+ {
31336
+ method: "POST",
31337
+ headers: {
31338
+ "Content-Type": "application/json"
31339
+ },
31340
+ body: JSON.stringify({
31341
+ email: user.email,
31342
+ password,
31343
+ returnSecureToken: false
31344
+ })
31345
+ }
31346
+ );
31347
+ const data = await response.json();
31348
+ if (!response.ok) {
31349
+ const errorMessage = data.error?.message || "Authentication failed";
31350
+ strapi2.log.debug(`checkPassword: password invalid for user ${user.email}: ${errorMessage}`);
31351
+ if (errorMessage === "INVALID_PASSWORD" || errorMessage === "INVALID_LOGIN_CREDENTIALS" || errorMessage.includes("INVALID")) {
31352
+ return { valid: false };
31353
+ }
31354
+ return { valid: false };
31355
+ }
31356
+ return { valid: true };
31357
+ } catch (error2) {
31358
+ strapi2.log.error("checkPassword error:", error2);
31359
+ throw new ApplicationError$2("Failed to verify password");
31360
+ }
31235
31361
  }
31236
31362
  });
31237
31363
  const passwordResetTemplate = {
@@ -75,6 +75,16 @@ declare const _default: {
75
75
  type: string;
76
76
  default: string;
77
77
  };
78
+ includeCredentialsInPasswordResetLink: {
79
+ type: string;
80
+ default: boolean;
81
+ description: string;
82
+ };
83
+ includeCredentialsInVerificationLink: {
84
+ type: string;
85
+ default: boolean;
86
+ description: string;
87
+ };
78
88
  };
79
89
  };
80
90
  };
@@ -58,5 +58,14 @@ declare const firebaseController: {
58
58
  * @returns { success: true, message: "Email verified successfully" }
59
59
  */
60
60
  verifyEmail(ctx: Context): Promise<Context>;
61
+ /**
62
+ * Check password - validates a password against the authenticated user's Firebase account
63
+ * POST /api/firebase-authentication/checkPassword
64
+ * Authenticated endpoint - requires valid JWT (enforced by is-authenticated policy)
65
+ *
66
+ * @param ctx - Koa context with { password } in body
67
+ * @returns { valid: true } or { valid: false }
68
+ */
69
+ checkPassword(ctx: Context): Promise<void>;
61
70
  };
62
71
  export default firebaseController;
@@ -10,6 +10,7 @@ declare const _default: {
10
10
  resetPasswordWithToken(ctx: import("koa").Context): Promise<void>;
11
11
  sendVerificationEmail(ctx: import("koa").Context): Promise<void>;
12
12
  verifyEmail(ctx: import("koa").Context): Promise<import("koa").Context>;
13
+ checkPassword(ctx: import("koa").Context): Promise<void>;
13
14
  };
14
15
  userController: {
15
16
  list: (ctx: import("koa").Context | import("koa").DefaultContext) => Promise<void>;
@@ -31,6 +31,7 @@ declare const _default: {
31
31
  resetPasswordWithToken(ctx: import("koa").Context): Promise<void>;
32
32
  sendVerificationEmail(ctx: import("koa").Context): Promise<void>;
33
33
  verifyEmail(ctx: import("koa").Context): Promise<import("koa").Context>;
34
+ checkPassword(ctx: import("koa").Context): Promise<void>;
34
35
  };
35
36
  userController: {
36
37
  list: (ctx: import("koa").Context | import("koa").DefaultContext) => Promise<void>;
@@ -106,6 +107,8 @@ declare const _default: {
106
107
  magicLinkExpiryHours: any;
107
108
  emailVerificationUrl: any;
108
109
  emailVerificationEmailSubject: any;
110
+ includeCredentialsInPasswordResetLink: any;
111
+ includeCredentialsInVerificationLink: any;
109
112
  }>;
110
113
  setFirebaseConfigJson(requestBody: any): Promise<any>;
111
114
  delFirebaseConfigJson: () => Promise<any>;
@@ -208,6 +211,9 @@ declare const _default: {
208
211
  success: boolean;
209
212
  message: string;
210
213
  }>;
214
+ checkPassword(user: any, password: string): Promise<{
215
+ valid: boolean;
216
+ }>;
211
217
  };
212
218
  templateService: ({ strapi }: {
213
219
  strapi: any;
@@ -344,6 +350,16 @@ declare const _default: {
344
350
  type: string;
345
351
  default: string;
346
352
  };
353
+ includeCredentialsInPasswordResetLink: {
354
+ type: string;
355
+ default: boolean;
356
+ description: string;
357
+ };
358
+ includeCredentialsInVerificationLink: {
359
+ type: string;
360
+ default: boolean;
361
+ description: string;
362
+ };
347
363
  };
348
364
  };
349
365
  };
@@ -131,5 +131,16 @@ declare const _default: ({ strapi }: {
131
131
  success: boolean;
132
132
  message: string;
133
133
  }>;
134
+ /**
135
+ * Check if a password is valid for the authenticated user
136
+ * Uses Firebase Identity Toolkit API to verify the password
137
+ *
138
+ * @param user - Authenticated user from ctx.state.user
139
+ * @param password - Password to check
140
+ * @returns { valid: true } or { valid: false }
141
+ */
142
+ checkPassword(user: any, password: string): Promise<{
143
+ valid: boolean;
144
+ }>;
134
145
  };
135
146
  export default _default;
@@ -17,6 +17,8 @@ declare const _default: {
17
17
  magicLinkExpiryHours: any;
18
18
  emailVerificationUrl: any;
19
19
  emailVerificationEmailSubject: any;
20
+ includeCredentialsInPasswordResetLink: any;
21
+ includeCredentialsInVerificationLink: any;
20
22
  }>;
21
23
  setFirebaseConfigJson(requestBody: any): Promise<any>;
22
24
  delFirebaseConfigJson: () => Promise<any>;
@@ -119,6 +121,9 @@ declare const _default: {
119
121
  success: boolean;
120
122
  message: string;
121
123
  }>;
124
+ checkPassword(user: any, password: string): Promise<{
125
+ valid: boolean;
126
+ }>;
122
127
  };
123
128
  templateService: ({ strapi }: {
124
129
  strapi: any;
@@ -31,6 +31,8 @@ declare const _default: ({ strapi }: {
31
31
  magicLinkExpiryHours: any;
32
32
  emailVerificationUrl: any;
33
33
  emailVerificationEmailSubject: any;
34
+ includeCredentialsInPasswordResetLink: any;
35
+ includeCredentialsInVerificationLink: any;
34
36
  }>;
35
37
  /**
36
38
  * Stores and encrypts Firebase configuration including Web API key and password reset settings
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-firebase-authentication",
3
- "version": "1.2.4",
3
+ "version": "1.3.2",
4
4
  "description": "Allows easy integration between clients utilizing Firebase for authentication and Strapi",
5
5
  "license": "MIT",
6
6
  "repository": {