Forgot Password and Reset Password 6 Digits Code

Hello Everyone,

Here is an example of how you can make Reset/Forgot Password with 6 digit code instead of a long string.
be advised that the longer the code its harder to crack it.

under following folder:

src>extensions>users-permissions

create file:

strapi-server.js

and inside paste following code:

"use strict";

const crypto = require("crypto");
const _ = require("lodash");
const utils = require("@strapi/utils");
const { getService } = require("@strapi/plugin-users-permissions/server/utils");
const {
  validateForgotPasswordBody,
} = require("@strapi/plugin-users-permissions/server/controllers/validation/auth");

const { getAbsoluteAdminUrl, getAbsoluteServerUrl, sanitize } = utils;

const sanitizeUser = (user, ctx) => {
  const { auth } = ctx.state;
  const userSchema = strapi.getModel("plugin::users-permissions.user");

  return sanitize.contentAPI.output(user, userSchema, { auth });
};

module.exports = (plugin) => {
  plugin.routes["content-api"].routes.unshift({
    method: "POST",
    path: "/auth/forgot-password-mobile",
    handler: "auth.forgotPasswordMobile",
    config: {
      middlewares: ["plugin::users-permissions.rateLimit"],
      prefix: "",
    },
  });

  plugin.controllers.auth.forgotPasswordMobile = async (ctx) => {
    const { email } = await validateForgotPasswordBody(ctx.request.body);
    const pluginStore = await strapi.store({
      type: "plugin",
      name: "users-permissions",
    });
    const emailSettings = await pluginStore.get({ key: "email" });
    const advancedSettings = await pluginStore.get({ key: "advanced" });

    // Find the user by email.
    const user = await strapi
      .query("plugin::users-permissions.user")
      .findOne({ where: { email: email.toLowerCase() } });

    if (!user || user.blocked) {
      return ctx.send({ ok: true });
    }
    console.log("start custom controller2");
    // Generate random token.
    const userInfo = await sanitizeUser(user, ctx);

    const resetPasswordToken = crypto.randomInt(100000, 999999).toString(); //crypto.randomBytes(3).toString("hex");

    const resetPasswordSettings = _.get(
      emailSettings,
      "reset_password.options",
      {}
    );
    const emailBody = await getService("users-permissions").template(
      resetPasswordSettings.message,
      {
        URL: advancedSettings.email_reset_password,
        SERVER_URL: getAbsoluteServerUrl(strapi.config),
        ADMIN_URL: getAbsoluteAdminUrl(strapi.config),
        USER: userInfo,
        TOKEN: resetPasswordToken,
      }
    );

    const emailObject = await getService("users-permissions").template(
      resetPasswordSettings.object,
      {
        USER: userInfo,
      }
    );

    const emailToSend = {
      to: user.email,
      from:
        resetPasswordSettings.from.email || resetPasswordSettings.from.name
          ? `${resetPasswordSettings.from.name} <${resetPasswordSettings.from.email}>`
          : undefined,
      replyTo: resetPasswordSettings.response_email,
      subject: emailObject,
      text: emailBody,
      html: emailBody,
    };

    // NOTE: Update the user before sending the email so an Admin can generate the link if the email fails
    await getService("user").edit(user.id, { resetPasswordToken });

    // Send an email to the user.
    await strapi.plugin("email").service("email").send(emailToSend);

    ctx.send({ ok: true });
  };

  return plugin;
};

this will generate a new route under Settings menu that you will need to allow access:

forgotPasswordMobile

if you want to change the length of the number generated, change this:

crypto.randomInt(100000, 999999)

this is update in TS - BUT ITS NOT TESTED please let me know if it works :smiley:

import crypto from "crypto";
import _ from "lodash";
import utils, { yup, validateYupSchema } from "@strapi/utils";

const { getAbsoluteAdminUrl, getAbsoluteServerUrl, sanitize } = utils;

const forgotPasswordSchema = yup
  .object({
    email: yup.string().email().required(),
  })
  .noUnknown();

const sanitizeUser = (user: any, ctx: any) => {
  const { auth } = ctx.state;
  const userSchema = strapi.getModel("plugin::users-permissions.user");

  return sanitize.contentAPI.output(user, userSchema, { auth });
};

module.exports = (plugin: any) => {
  plugin.controllers.auth.forgotPasswordMobile = async (ctx: any) => {
    const { email: email } = await validateYupSchema(forgotPasswordSchema)(
      ctx.request.body
    );
    const pluginStore = strapi.store({
      type: "plugin",
      name: "users-permissions",
    });
    const emailSettings: any = await pluginStore.get({ key: "email" });
    const advancedSettings: any = await pluginStore.get({ key: "advanced" });

    // Find the user by email.
    const user = await strapi
      .query("plugin::users-permissions.user")
      .findOne({ where: { email: email.toLowerCase() } });

    if (!user || user.blocked) {
      return ctx.send({ ok: true });
    }
    console.log("start custom controller2");
    // Generate random token.
    const userInfo = await sanitizeUser(user, ctx);

    const resetPasswordToken = crypto.randomInt(100000, 999999).toString(); //crypto.randomBytes(3).toString("hex");

    const resetPasswordSettings: any = _.get(
      emailSettings,
      "reset_password.options",
      {}
    );

    const emailBody = await strapi
      .plugin("users-permissions")
      .service("users-permissions")
      .template(resetPasswordSettings.message, {
        URL: advancedSettings.email_reset_password,
        SERVER_URL: getAbsoluteServerUrl(strapi.config),
        ADMIN_URL: getAbsoluteAdminUrl(strapi.config),
        USER: userInfo,
        TOKEN: resetPasswordToken,
      });

    const emailObject = await strapi
      .plugin("users-permissions")
      .service("users-permissions")
      .template(resetPasswordSettings.object, {
        USER: userInfo,
      });

    const emailToSend = {
      to: user.email,
      from:
        resetPasswordSettings.from.email || resetPasswordSettings.from.name
          ? `${resetPasswordSettings.from.name} <${resetPasswordSettings.from.email}>`
          : undefined,
      replyTo: resetPasswordSettings.response_email,
      subject: emailObject,
      text: emailBody,
      html: emailBody,
    };

    // NOTE: Update the user before sending the email so an Admin can generate the link if the email fails
    await await strapi
      .plugin("users-permissions")
      .service("user")
      .edit(user.id, { resetPasswordToken });

    // Send an email to the user.
    await strapi.plugin("email").service("email").send(emailToSend);

    ctx.send({ ok: true });
  };

  plugin.routes["content-api"].routes.unshift({
    method: "POST",
    path: "/auth/forgot-password-mobile",
    handler: "auth.forgotPasswordMobile",
    config: {
      middlewares: ["plugin::users-permissions.rateLimit"],
      prefix: "",
    },
  });

  return plugin;
};

2 Likes

it hellpsss thankksssss

If you are getting an exports error, please add this code to the node_modules/@strapi/plugin-users-permissions/package.json in the exports object:

"./server/utils": {
  "source": "./server/utils/index.js",
  "require": "./server/utils/index.js",
  "default": "./server/utils/index.js"
},
"./server/controllers/validation/auth": {
  "source": "./server/controllers/validation/auth.js",
  "require": "./server/controllers/validation/auth.js",
  "default": "./server/controllers/validation/auth.js"
},