Вопрос или проблема
import UserProfile из '../components/profile/user-profile';
// import { getSession } из 'next-auth/react';
import { getServerSession } из "next-auth/next"
import { authOptions } из './api/auth/[...nextauth]';
function ProfilePage() {
return <UserProfile />;
}
export async function getServerSideProps(context){
const session = await getServerSession(context.req, context.res, authOptions)
console.log('здесь')
console.log(session)
if (!session) {
return{
redirect: {
destination: '/auth',
permanent: false
}
}
}
return{
props: { session }
}
}
export default ProfilePage;
//Параметры аутентификации
import NextAuth из "next-auth";
import CredentialsProvider из "next-auth/providers/credentials"; // Обновить импорт для провайдера учетных данных
import connectToDatabase из "../../../ib/db";
import { verifyPassword } из "../../../ib/auth";
export const authOptions = {
session: {
jwt: true,
},
providers: [
CredentialsProvider({
name: 'Credentials',
async authorize(credentials) {
const client = await connectToDatabase();
const userCollection = client.db().collection('users');
const user = await userCollection.findOne({ email: credentials.email });
if (!user) {
client.close();
throw new Error('Пользователь не найден!');
}
const isValid = await verifyPassword(credentials.password, user.password);
if (!isValid) {
client.close();
throw new Error('Неверный пароль');
}
client.close();
return { email: user.email };
},
}),
],
};
export default NextAuth(authOptions);
//api маршрут
import { getServerSession } из "next-auth/next";
import connectToDatabase из "../../../ib/db";
import { hashPassword, verifyPassword } из "../../../ib/auth";
import { authOptions } из "../auth/[...nextauth]";
import { getSession } из "next-auth/react";
async function handler(req, res) {
if (req.method !== "PATCH") {
return res.status(405).json({ message: "Метод не разрешен" });
}
const session = await getServerSession(req, res, authOptions);
if (!session) {
return res.status(401).json({ message: "Запрос не авторизован" });
}
const userEmail = session.user.email;
const { oldPassword, newPassword } = req.body;
const client = await connectToDatabase();
const usersCollection = client.db().collection('users');
const user = await usersCollection.findOne({ email: userEmail });
if (!user) {
client.close();
return res.status(404).json({ message: 'Пользователь не найден' });
}
const currentPassword = user.password;
const passwordsAreEqual = await verifyPassword(oldPassword, currentPassword); // Добавлено `await`
if (!passwordsAreEqual) {
client.close();
return res.status(403).json({ message: "Вы аутентифицированы, но не авторизованы" });
}
const hashedPassword = await hashPassword(newPassword);
const result = await usersCollection.updateOne(
{ email: userEmail },
{ $set: { password: hashedPassword } }
);
client.close();
return res.status(200).json({ message: "Пароль обновлен" });
}
export default handler;
в приведенном выше коде мне нужно получить текущую сессию пользователя внутри серверного рендеринга. Для клиентской стороны функция getSeesion() работает нормально, но внутри api маршрутов и getServerProps функция getSession() не работает, и теперь я пытаюсь использовать getServerSession(), который очищает все куки, и я получаю null сессию, как мне решить эту проблему
Также я получаю следующее сообщение об ошибке
[next-auth][error][JWT_SESSION_ERROR]
https://next-auth.js.org/errors#jwt_session_error ошибка расшифровки {
message: 'ошибка расшифровки',
stack: 'JWEDecryptionFailed: операция расшифровки не удалась\n' +
' at gcmDecrypt (D:\\personal\\authentication\\node_modules\\jose\\dist\\node\\cjs\\runtime\\decrypt.js:67:15)\n' +
' at decrypt (D:\\personal\\authentication\\node_modules\\jose\\dist\\node\\cjs\\runtime\\decrypt.js:92:20)\n' +
' at flattenedDecrypt (D:\\personal\\authentication\\node_modules\\jose\\dist\\node\\cjs\\jwe\\flattened\\decrypt.js:143:52)\n' +
' at async compactDecrypt (D:\\personal\\authentication\\node_modules\\jose\\dist\\node\\cjs\\jwe\\compact\\decrypt.js:18:23)\n' +
' at async jwtDecrypt (D:\\personal\\authentication\\node_modules\\jose\\dist\\node\\cjs\\jwt\\decrypt.js:8:23)\n' +
' at async Object.decode (D:\\personal\\authentication\\node_modules\\jose\\dist\\node\\cjs\\jwt\\index.js:66:7)\n' +
' at async Object.session (D:\\personal\\authentication\\node_modules\\next-auth\\node_modules\\next-auth\\core\\routes\\session.js:43:28)\n' +
' at async AuthHandler (D:\\personal\\authentication\\node_modules\\next-auth\\node_modules\\next-auth\\core\\index.js:165:27)\n' +
' at async getServerSession (D:\\personal\\authentication\\node_modules\\next-auth\\node_modules\\next-auth\\next\\index.js:159:19)\n' +
' at async getServerSideProps (webpack-internal:///./pages/profile.js:25:21)',
name: 'JWEDecryptionFailed'
}
Ответ или решение
Для того чтобы получить текущую сессию пользователя внутри функции getServerSideProps
и внутри API маршрутов в Next.js, можно использовать функцию getServerSession
из библиотеки next-auth
.
1. Использование getServerSession
в getServerSideProps
Похоже, что вы уже используете правильный подход, однако сталкиваетесь с ошибкой, которая связана с расшифровкой JWT. Это может произойти по нескольким причинам, в том числе из-за проблем с конфигурацией ключей шифрования или сессий.
Пример вашего кода с getServerSession
в getServerSideProps
:
import UserProfile from '../components/profile/user-profile';
import { getServerSession } from "next-auth/next";
import { authOptions } from './api/auth/[...nextauth]';
function ProfilePage() {
return <UserProfile />;
}
export async function getServerSideProps(context){
const session = await getServerSession(context.req, context.res, authOptions);
if (!session) {
return {
redirect: {
destination: '/auth',
permanent: false
}
}
}
return {
props: { session }
}
}
export default ProfilePage;
2. Использование getServerSession
в API маршрутах
Аналогично, внутри API маршрутов вы также правильно используете getServerSession
. Пример:
import { getServerSession } from "next-auth/next";
import connectToDatabase from "../../../ib/db";
import { hashPassword, verifyPassword } from "../../../ib/auth";
import { authOptions } from "../auth/[...nextauth]";
async function handler(req, res) {
if (req.method !== "PATCH") {
return res.status(405).json({ message: "Method not allowed" });
}
const session = await getServerSession(req, res, authOptions);
if (!session) {
return res.status(401).json({ message: "Unauthorized Request" });
}
const userEmail = session.user.email;
const { oldPassword, newPassword } = req.body;
const client = await connectToDatabase();
const usersCollection = client.db().collection('users');
const user = await usersCollection.findOne({ email: userEmail });
if (!user) {
client.close();
return res.status(404).json({ message: 'User Not Found' });
}
const currentPassword = user.password;
const passwordsAreEqual = await verifyPassword(oldPassword, currentPassword);
if (!passwordsAreEqual) {
client.close();
return res.status(403).json({ message: "You are authenticated but not authorized" });
}
const hashedPassword = await hashPassword(newPassword);
await usersCollection.updateOne(
{ email: userEmail },
{ $set: { password: hashedPassword } }
);
client.close();
return res.status(200).json({ message: "Password updated" });
}
export default handler;
Возможные ошибки и их устранение
Ошибка JWEDecryptionFailed
, которую вы наблюдаете, может быть связана с неправильными настройками шифрования JWT. Обратите внимание на следующие возможные причины:
-
Проверка ключа шифрования: Убедитесь, что вы правильно настроили
NEXTAUTH_SECRET
в переменных окружения. Это значение должно быть стабильным и уникальным.NEXTAUTH_SECRET=ваш_секретный_ключ
-
Смена браузера или использование инкогнито: Иногда сессии могут повредиться, если вы меняете браузер или используете режим инкогнито. Попробуйте удалить куки и повторно войти в систему.
-
Тестирование на локальном сервере: Убедитесь, что вы испытываете вашу аутентификацию в подходящей среде (на локальном сервере). Попробуйте запустить
npm run dev
и протестировать вашу реализацию.
Заключение
Если вы выполните все указанные шаги и проверите, что ваши конфигурации установлены правильно, вы сможете успешно использовать getServerSession
в ваших API маршрутах и в функции getServerSideProps
. Если проблемы продолжаются, можно рассмотреть возможность создания нового JWT-секрета и протестировать, остается ли проблема.