Attention: This page is 28 days older than the English version and might be outdated. If you're a native speaker of this language and would like to contribute to the project, please consider updating this page to match the latest English version.
You can also view the English version of this page.
NextAuth.js
Когда вы хотите иметь систему аутентификации в вашем приложении Next.js, NextAuth.js - отличное решение, чтобы не заморачиваться с реализацией сложной безопасности самостоятельно. Он имеет обширный список провайдеров для быстрого добавления аутентификации OAuth и предоставляет адаптеры для многих баз данных и ORM.
Провайдер контекста
В точке входа вашего приложения вы увидите, что ваше приложение обернуто в SessionProvider↗:
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
Этот провайдер контекста позволяет вашему приложению получить доступ к данным сессии из любого места вашего приложения, не передавая их как пропсы:
import { useSession } from "next-auth/react";
const User = () => {
const { data: session } = useSession();
if (!session) {
// Handle unauthenticated state, e.g. render a SignIn component
return <SignIn />;
}
return <p>Welcome {session.user.name}!</p>;
};
Получение сессии на сервере
Иногда вам может понадобиться запросить сессию на сервере. Чтобы сделать это, предварительно получите сессию с помощью функции-помощника getServerAuthSession
, которую предоставляет create-t3-app
, и передайте ее на клиент с помощью getServerSideProps
:
import { getServerAuthSession } from "../server/auth";
import { type GetServerSideProps } from "next";
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
return {
props: { session },
};
};
const User = () => {
const { data: session } = useSession();
// NOTE: `session` wont have a loading state since it's already prefetched on the server
...
}
Включение user.id
в сессию
create-t3-app
настроен для использования session callback↗ в конфигурации NextAuth.js для включения ID пользователя в объект session
.
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
Это связано с файлом объявления типов, чтобы убедиться, что user.id
типизирован при доступе к объекту session
. Подробнее о Module Augmentation
↗ в документации NextAuth.js.
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session {
user?: {
id: string;
} & DefaultSession["user"];
}
}
Такой же шаблон может быть использован для добавления любых других данных в объект session
, например, поля role
, но не следует злоупотреблять для хранения конфиденциальных данных на клиенте.
Использование с tRPC
При использовании NextAuth.js с tRPC вы можете создавать повторно используемые, защищенные процедуры с помощью middleware↗. Это позволяет вам создавать процедуры, которые могут быть доступны только аутентифицированным пользователям. create-t3-app
настраивает все это для вас, позволяя вам легко получать доступ к объекту сессии в аутентифицированных процедурах.
Это делается в два шага:
- Возьмите сессию из заголовков запроса с помощью функции
getServerSession
↗. Преимущество использованияgetServerSession
вместо обычногоgetSession
заключается в том, что это server-side функция и она не вызывает ненужных вызовов fetch.create-t3-app
создает вспомогательную функцию, которая абстрагирует этот особый API.
export const getServerAuthSession = async (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return await getServerSession(ctx.req, ctx.res, authOptions);
};
Используя эту вспомогательную функцию, мы можем получить сессию и передать ее в контекст tRPC:
import { getServerAuthSession } from "../auth";
export const createContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
const session = await getServerAuthSession({ req, res });
return await createContextInner({
session,
});
};
- Создайте tRPC middleware, которое проверяет, аутентифицирован ли пользователь. Затем мы используем middleware в
protectedProcedure
. Любой вызывающий эти процедуры должен быть аутентифицирован, иначе будет сгенерирована ошибка, которую можно правильно обработать на стороне клиента.
const isAuthed = t.middleware(({ ctx, next }) => {
if (!ctx.session || !ctx.session.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
export const protectedProcedure = t.procedure.use(isAuthed);
Обект сессии - это легкое, минимальное представление пользователя и содержит только несколько полей. При использовании protectedProcedures
у вас есть доступ к идентификатору пользователя, который можно использовать для получения большего количества данных из базы данных.
const userRouter = router({
me: protectedProcedure.query(async ({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
Использование с Prisma
Чтобы заставить NextAuth.js и Prisma работать вместе, необходимо большое количество начальной настройки↗. create-t3-app
выполняет все это для вас, и если вы выберете одновременно и Prisma, и NextAuth.js, вы получите полностью работающую систему аутентификации со всеми предварительно настроенными, необходимыми моделями. Мы предоставляем вашему сгенерированому приложению предварительно настроеный провайдер Discord OAuth, который мы выбрали потому, с ним легче всего начать - просто укажите свои токены в .env
и вы готовы к работе. Однако вы можете легко добавить больше провайдеров, следуя докуменетации NextAuth.js↗. Обратите внимание, что некоторые провайдеры требуют дополнительных полей для добавления в определенные модели. Мы рекомендуем вам прочитать документацию для провайдера, который вы хотите использовать, чтобы убедиться, что у вас есть все необходимые поля.
Добавление новых полей в ваши модели
Когда вы добавляете новые поля в любую из моделей User
, Account
, Session
или VerificationToken
(в большинстве случаев вам потребуется только изменить модель User
), вам нужно иметь в виду, что адаптер Prisma↗ автоматически создает поля в этих моделях при регистрации новых пользователей и входе в систему. Поэтому, добавляя новые поля в эти модели, вы должны предоставить значения по умолчанию для них, поскольку адаптер не знает о них.
Если например, вы хотите добавить role
в модель User
, вам нужно будет предоставить значение по умолчанию для поля role
. Это делается путем добавления значения @default
к полю role
в модели User
:
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
Использование с Next.js middleware
Использование NextAuth.js с Next.js middleware требует использования стратегии сеанса JWT↗ для аутентификации. Это связано с тем, что middleware может получить доступ к сессионной cookie только в том случае, если это JWT. По умолчанию, create-t3-app
настроен на использование default стратегии базы данных, в сочетании с Prisma в качестве адаптера базы данных.
Настраиваем DiscordProvider по умолчанию
- Перейдите в раздел Applications в Discord Developer Portal↗, и нажмите на “New Application”
- В меню настроек перейдите к “OAuth2 => General”
- Скопируйте Client ID и вставьте его в
DISCORD_CLIENT_ID
в.env
. - Возле Client Secret нажмите “Reset Secret” и скопируйте эту строку в
DISCORD_CLIENT_SECRET
в.env
. Будьте осторожны, поскольку вы больше не сможете увидеть этот секрет, и сброс его приведет к тому, что существующий истечет. - Нажмите “Add Redirect” и вставьте
<app url>/api/auth/callback/discord
(пример для локальной разработки:http://localhost:3000/api/auth/callback/discord↗
) - Сохраните изменения
- Возможно, но не рекомендуется, использовать одно и то же приложение Discord для разработки и продакшена. Вы также можете рассмотреть Mocking the Provider↗ во время разработки.
Полезные ресурсы
Ресурс | Ссылка |
---|---|
Документация NextAuth.js | https://next-auth.js.org/↗ |
NextAuth.js GitHub | https://github.com/nextauthjs/next-auth↗ |
tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth↗ |