如何使用 NextAuth 和凭据提供程序创建重置密码

问题描述 投票:0回答:3

如何使用 mongo db 的下一个身份验证凭据提供程序创建一个简单的重置密码 我有这样的用户模式

const userSchema = new mongoose.Schema<UserSchemaType>(
    {
        name: { type: String, required: true },
        email: { type: String, required: true, unique: true },
        password: { type: String, required: true },
        img: { type: String, required: true },
        isAdmin: { type: Boolean, required: true, default: false },
    },
    {
        timestamps: true,
    }
);

我的下一个授权看起来像这样

    providers: [
        CredentialsProvider({
            async authorize(credentials) {
                await db.connect();
                const user = await User.findOne({
                    email: credentials.email,
                });

                if (user && bcryptjs.compareSync(credentials.password, user.password)) {
                    return {
                        _id: user._id,
                        name: user.name,
                        email: user.email,
                        image: user.img,
                        isAdmin: user.isAdmin,
                    };
                }
                throw new Error('Invalid email or password');
            },
        }),
    ],
});

是否有一个简单的示例来实现下次身份验证重置密码

authentication next.js passwords next-auth forgot-password
3个回答
4
投票

我不认为

next-auth
为此提供任何特殊功能。您必须实施一般流程。用户应该有
Forgot Password
按钮,然后您将请求发送到 next.js api 后端。 “pages/api/forgot.js”

import jwt from "jsonwebtoken";

handler.post(async (req, res) => {
  try {
    await db.connectDb();
    const { email } = req.body;
    const user = await User.findOne({ email });
    if (!user) {
      return res.status(400).json({ message: "Email does not exist." });
    }
   // create token with jwt 
    const user_token =jwt.sign(user._id, process.env.RESET_TOKEN_SECRET, {
expiresIn: "1h",
});
    // you should create "pages/reset/[token].js" dynamic page
    const url = `${process.env.BASE_URL}/reset/${user_id}`;
    // you need to implement sedning email maybe using `nodemailer`
    // create this function for your case
    sendEmail(email, url, "Reset your password.");
    // you should disconnect the db here
    res.json({
      message: "An email has been sent to you to reset your password.",
    });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
});

“pages/reset/[token].js”页面您将有一个包含 2 个输入的表单。 “密码”和“确认密码”。用户单击重置按钮后,您将密码和解密的令牌(我们使用 user_id 创建了令牌)发送到另一个后端 api:“pages/api/reset.js”。该后端将获取

user_id
和密码,查询数据库并更改密码

handler.put(async (req, res) => {
  try {
    await db.connectDb();
    const { user_id, password } = req.body;
    const user = await User.findById(user_id);
    if (!user) {
      return res.status(400).json({ message: "Account does not exist." });
    }
    const hashedPassword = await bcrypt.hash(password, 12);
    await user.updateOne({
      password: hashedPassword,
    });
    res.status(200).json({ email: user.email });
    // you should disconnect the db 
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
});

1
投票

来自文档 - https://next-auth.js.org/providers/credentials

为基于凭据的身份验证提供的功能是 故意限制以阻止使用密码,因为 与它们相关的固有安全风险以及额外的 与支持用户名和密码相关的复杂性。

如果您确实需要此功能,也许您可以使用电子邮件提供商并进行自定义。

https://next-auth.js.org/configuration/providers/email


0
投票

这是一个人如何在register/route.ts中实现注册。

我认为有一个类似的方法,通过创建一个按钮,使用 PUT 请求而不是 POST 请求转到重置密码/route.ts。

祝你好运!

import { NextResponse } from "next/server";
import prisma from "@/prisma/prisma";
import { createUserSchema } from "@/lib/user-schema";
import { ZodError } from "zod";
import { hashPassword } from "../../../app/utils/passwordUtils";

export async function POST(req: Request) {
  const { name, email, password } = createUserSchema.parse(await req.json());

  const { hashString , saltString} = await hashPassword(password);
  console.log("hello", {hashString, saltString})
  try {
    

    const user = await prisma.user.create({
      data: {
        name,
        email: email.toLowerCase(),
        password: hashString,
        salt: saltString,
      },
    });

    return NextResponse.json({
      user: {
        name: user.name,
        email: user.email,
      },
    });
  } catch (error: any) {
    if (error instanceof ZodError) {
      return NextResponse.json(
        {
          status: "error",
          message: "Validation failed",
          errors: error.errors,
        },
        { status: 400 }
      );
    }

    if (error.code === "P2002") {
      return NextResponse.json(
        {
          status: "fail",
          message: "user with that email already exists",
        },
        { status: 409 }
      );
    }

    return NextResponse.json(
      {
        status: "error",
        message: error.message || "Internal Server Error",
      },
      { status: 500 }
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.