Next-Auth:如何使用电子邮件+密码凭据提供者处理注册?

26

如何使用自定义凭据提供程序(电子邮件 + 密码)处理注册

目前我的[...nextauth].js看起来像这样:

import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'
import axios from 'axios'
import jwt from "next-auth/jwt";

const YOUR_API_ENDPOINT = process.env.NEXT_PUBLIC_API_ROOT + 'auth/store'

const providers = [
    Providers.Credentials({
        name: 'Credentials',
        authorize: async (credentials) => {

            try {
                const user = await axios.post(YOUR_API_ENDPOINT,
                    {

                            password: credentials.password,
                            username: credentials.email

                    },
                    {
                        headers: {
                            accept: '*/*',
                            'Content-Type': 'application/json'
                        }
                    })

                console.log('ACCESS TOKEN ----> ' + JSON.stringify(user.data.access_token, null, 2));

                if (user) {

                    return {status: 'success', data: user.data}
                }

            } catch (e) {
                const errorMessage = e.response.data.message
                // Redirecting to the login page with error messsage in the URL
                throw new Error(errorMessage + '&email=' + credentials.email)
            }

        }
    })
]

const callbacks = {

    /*
    |--------------------------------------------------------------------------
    | Callback : JWT
    |--------------------------------------------------------------------------
    */
    async jwt(token, user, account, profile, isNewUser) {

        if (user) {
            token.accessToken = user.data.access_token
        }

        return token
    },

    /*
    |--------------------------------------------------------------------------
    | Callback : Session
    |--------------------------------------------------------------------------
    */
    async session(session, token) {

        // Store Access Token to Session
        session.accessToken = token.accessToken

        /*
        |--------------------------------------------------------------------------
        | Get User Data
        |--------------------------------------------------------------------------
        */

        const API_URL = 'http://localhost:3000/api';

        const config = {
            headers: { Authorization: `Bearer ${token.accessToken}` }
        };

        let userData;

        await axios.get(`${API_URL}/user`, config)
            .then(response => {

                userData = {
                    id:                             response.data.id,
                    uuid:                           response.data.uuid,
                    username:                       response.data.username,
                    avatar_location:                response.data.avatar_location,
                    gender_id:                      response.data.gender_id,
                    date_of_birth:                  response.data.date_of_birth,
                    country_id:                     response.data.country_id,
                    location:                       response.data.location,
                    about_me:                       response.data.about_me,
                    interests:                      response.data.interests,
                    website:                        response.data.website,
                    timezone:                       response.data.timezone,
                    full_name:                      response.data.full_name,
                    formatted_created_at:           response.data.formatted_created_at,
                    formatted_last_seen:            response.data.formatted_last_seen,
                    album_count:                    response.data.album_count,
                    total_unread_message_count:     response.data.total_unread_message_count,
                };

                // Store userData to Session
                session.user = userData

            }).catch((error) => {

                // Error
                if (error.response) {
                    // The request was made and the server responded with a status code
                    // that falls out of the range of 2xx
                    // console.log(error.response.data);
                    // console.log(error.response.status);
                    // console.log(error.response.headers);
                    console.log('error.response: ' + error.request);

                } else if (error.request) {
                    // The request was made but no response was received
                    // `error.request` is an instance of XMLHttpRequest in the
                    // browser and an instance of
                    // http.ClientRequest in node.js
                    console.log('error.request: ' + error.request);



                } else {
                    // Something happened in setting up the request that triggered an Error
                    console.log('Error', error.message);
                }
                console.log(error.config);

            });

        return session
    }
}

const options = {
    providers,
    callbacks,
    session: {
        // Use JSON Web Tokens for session instead of database sessions.
        // This option can be used with or without a database for users/accounts.
        // Note: `jwt` is automatically set to `true` if no database is specified.
        jwt: true,

        // Seconds - How long until an idle session expires and is no longer valid.
        maxAge: 30 * 24 * 60 * 60, // 30 days

        // Seconds - Throttle how frequently to write to database to extend a session.
        // Use it to limit write operations. Set to 0 to always update the database.
        // Note: This option is ignored if using JSON Web Tokens
        updateAge: 24 * 60 * 60, // 24 hours
    },
    secret: process.env.SECRET,
    jwt: {
        // signingKey: process.env.JWT_SIGNING_PRIVATE_KEY,
        //
        // // You can also specify a public key for verification if using public/private key (but private only is fine)
        // verificationKey: process.env.JWT_SIGNING_PUBLIC_KEY,
        //
        // // If you want to use some key format other than HS512 you can specify custom options to use
        // // when verifying (note: verificationOptions should include a value for maxTokenAge as well).
        // // verificationOptions = {
        // //   maxTokenAge: `${maxAge}s`, // e.g. `${30 * 24 * 60 * 60}s` = 30 days
        // //   algorithms: ['HS512']
        // // },

        secret: process.env.JWT_SECRET,
    },
    pages: {
        error: '/login' // Changing the error redirect page to our custom login page
    }
}

export default (req, res) => NextAuth(req, res, options)

我在网上找到的所有教程都只展示了如何实现登录/登录,但没有详细说明如何实现注册


2
我猜答案在这里:https://github.com/nextauthjs/next-auth/discussions/2285 - Aydin K.
1
似乎不鼓励使用凭据。 - Daniel
3个回答

28

注册是将用户注册并将新用户的凭据保存到数据库中的过程。它与next-auth无关。您需要创建一个表单,提交表单并将表单数据正确保存到数据库中。

当您登录并通过身份验证时,也就是您已经成为注册和真实用户时,next-auth接管了这个过程。一旦您通过安全检查并成功登录,next-auth为用户创建一个会话。

您可以查看v4的设置演示:next-auth 4 session returns null, next.js


1
如果您选择 strategy: "database",next-auth 将在您的数据库中保存一个新用户。因此,它提供了自己的“开箱即用”版本的注册功能。我想知道是否可以更新并依赖于它创建的这些“用户”记录,或者 next-auth 是否可以随时删除其中任何一条记录 (!)。 - Kawd
@SproutCoder,你能提供一些可用的注册演示示例作为参考吗? - Jayna Tanawala
我在选项中没有看到“strategy”属性。 - benwl

1
你可以添加多个提供者,就像登录一样,将数据从后端存储在会话中。
providers: [
    GoogleProvider({
        
    }),
    CredentialsProvider({
        id: "custom-login",
        type: "credentials",
        credentials: {},
        
    }),
    CredentialsProvider({
        id: "custom-signup",
        type: "credentials",
        credentials: {},
       
    })
]

如何调用注册?我真的不太明白你是如何做到的。在注册过程中,我应该如何存储来自后端服务器的JWT令牌? - undefined
我已经更新了我的回答。 - undefined
模仿登录以进行注册 - undefined
谢谢。这种做法被认为是“正确”的吗?还是更好让我的后端处理所有这些,使用PassportJS并将访问令牌存储在cookies中(并在useContext / Zustand中存储用户的姓名和可能的电子邮件)? - undefined

-4

next-auth 只支持登录(Sign In)、注册(Sign Up)和登出(Sign Out)。当用户第一次创建账户时,它会自动注册,无需进行新的注册流程。


7
虽然我不是这里的投票者,但这个回答只针对 OAuth 是正确的,而不是凭证提供程序。 - AaronHS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接