После долгого поиска документации по этой проблеме, наконец, я решил написать этот пост, чтобы помочь разработчикам, оказавшимся в такой же ситуации.
Адаптер Mongodb — это утилита, которая предоставляет нам «метод» для сохранения пользователей/учетных записей/сеансов в Mongodb с использованием таких поставщиков, как Google, Github и т. д. Но что произойдет, если вы захотите сохранить свои пользовательские данные в mongodb?
Сначала я использовал пакет mongoose для управления им, но nextauth дает нам реализацию, которая ускоряет процесс, не прибегая к другим внешним библиотекам, таким как mongoose. Нам просто нужно использовать MongoClient и написать небольшую утилиту, чтобы поддерживать связь.
Настройте наш адаптер
npm install next-auth @next-auth/mongodb-adapter mongodb
Как говорится в документации, адаптер Mongodb не обрабатывает соединения автоматически, поэтому нам нужно передать клиентское подключение к адаптеру.
Адаптер MongoDB не обрабатывает соединения автоматически, поэтому вам нужно убедиться, что вы передаете адаптеру
MongoClient
, который уже подключен. Ниже вы можете увидеть пример, как это сделать.
Клиент MongoDB
// This approach is taken from https://github.com/vercel/next.js/tree/canary/examples/with-mongodb import { MongoClient } from "mongodb"; if (!process.env.MONGODB_URI) { throw new Error('Invalid/Missing environment variable: "MONGODB_URI"'); } const uri = process.env.MONGODB_URI; const options = {}; let client; let clientPromise: Promise<MongoClient>; if (process.env.NODE_ENV === "development") { // In development mode, use a global variable so that the value // is preserved across module reloads caused by HMR (Hot Module Replacement). if (!global._mongoClientPromise) { client = new MongoClient(uri, options); global._mongoClientPromise = client.connect(); } clientPromise = global._mongoClientPromise; } else { // In production mode, it's best to not use a global variable. client = new MongoClient(uri, options); clientPromise = client.connect(); } // Export a module-scoped MongoClient promise. By doing this in a // separate module, the client can be shared across functions. export default clientPromise;
Не забудьте создать переменную среды в файле .env с uri mongodb.
Учетные данные и обратные вызовы
Вы можете использовать методы, предоставляемые адаптером next-auth, чтобы найти своего пользователя, например, getUserByEmail (ваш «[email protected]»). И, конечно же, вы можете взять это письмо из учетных данных, getUserByEmail(credentials.username)
import clientPromise from "@/app/lib/mongodb"; import { MongoDBAdapter } from "@next-auth/mongodb-adapter"; import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; import GitHubProvider from "next-auth/providers/github"; export const authOptions = { adapter: MongoDBAdapter(clientPromise), providers: [ GitHubProvider({ clientId: process.env.GITHUB_ID, clientSecret: process.env.GITHUB_SECRET, }), CredentialsProvider({ name: "credentials", credentials: { username: { label: "Username", type: "text", placeholder: "Aaron" }, password: { label: "Password", type: "password" }, }, async authorize(credentials, req) { // Find your user in the database using MongoDBAdapter const user = await authOptions.adapter.getUser( "6471f710f772cf139bc5142e" ); if (user) { return user; } else { return null; } }, }), ], secret: process.env.NEXTAUTH_SECRET, session: { // Set it as jwt instead of database strategy: "jwt", }, callbacks: { async jwt({ token, user }) { // Persist the OAuth access_token and or the user id to the token right after signin if (user) { token.accessToken = user.access_token; token.id = user.id; } return token; }, async session({ session, token }) { // Send properties to the client, like an access_token and user id from a provider. session.accessToken = token.accessToken; session.user.id = token.id; return session; }, }, }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
Обратите внимание: если вы хотите сохранить сеанс учетных данных, вам нужно установить session.strategy как «jwt». Поставщик учетных данных не сохраняет сеанс в базе данных.
Поставщик учетных данных можно использовать только в том случае, если для сеансов включены веб-токены JSON. Пользователи, прошедшие проверку подлинности с помощью поставщика учетных данных, не сохраняются в базе данных.
https://next-auth.js.org/configuration/providers/credentials
Даже вы можете сохранить пользовательские данные в сеансе пользователя. Просто передайте дополнительные параметры в обратный вызов сеанса.
Провайдер сеанса
Не забудьте обернуть layout.js компонентом SessionProvider, чтобы получить доступ пользователя ко всему приложению.
"use client"; import { SessionProvider } from "next-auth/react"; import "./globals.css"; export const metadata = { title: "Create Next App", description: "Generated by create next app", }; export default function RootLayout({ children }) { return ( <html lang="en"> <SessionProvider> <body>{children}</body> </SessionProvider> </html> ); }
Теперь вы можете получить доступ к URL-адресу https://localhost:3000/api/auth/signin/credentials и войти, используя свои учетные данные или через своего провайдера.
После этого у вас должен быть доступ к сессии и ее свойствам с помощью хука useSession.
А из бэкенда с помощью getServerSession.
import { authOptions } from "../auth/[...nextauth]/route"; import { getServerSession } from "next-auth"; export async function GET(Request) { const session = await getServerSession(authOptions); if (session) { return new Response(JSON.stringify(session), { status: 200 }); } else { return new Response("Not authenticated user!", { status: 401 }); } }
Ссылки
Github: https://github.com/aaronaira/next-auth-example-mongodbadapter
Linkedin: https://www.linkedin.com/in/aaron-aira/