Jump to content

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

Kiedy chcesz doda─ç system kont do swojej aplikacji Next.js, NextAuth.js to znakomite rozwi─ůzanie. Pozwala ono wdro┼╝y─ç z┼éo┼╝one systemy bezpiecze┼ästwa nie zmuszaj─ůc Ci─Ö przy tym do pisania ich w┼éasnor─Öcznie. NextAuth.js zawiera rozleg┼é─ů list─Ö provider├│w, kt├│re zapewni─ů Ci szybki spos├│b na dodanie OAutha. Paczka ta posiada r├│wnie┼╝ wiele adapter├│w dla baz danych i ORM├│w.

Context Provider

W pliku pages/_app.tsx zobaczy─ç mo┼╝esz, i┼╝ twoja aplikacja znajduje si─Ö w SessionProviderzeÔćŚ:

pages/_app.tsx
<SessionProvider session={session}>
  <Component {...pageProps} />
</SessionProvider>

Ten oto provider kontekstu pozwala twojej aplikacji na dost─Öp do danych sesji z ka┼╝dego miejsca, bez potrzeby przesy┼éania ich po ÔÇťpropsachÔÇŁ:

pages/users/[id].tsx
import { useSession } from "next-auth/react";

const User = () => {
  const { data: session } = useSession();

  if (!session) {
    // Obs┼éu┼╝ status nie bycia zalogowanym, np. wy┼Ťwietl komponent `SignIn`
    return <SignIn />;
  }

  return <p>Welcome {session.user.name}!</p>;
};

Otrzymywanie sesji po stronie serwera

Czasem mo┼╝esz chcie─ç otrzyma─ç sesj─Ö na serwerze. Aby to zrobi─ç, pobierz sesj─Ö korzystaj─ůc z funkcji pomocniczej getServerAuthSession dostarczanej przez Create T3 App a nast─Öpnie prze┼Ťlij j─ů do klienta korzystaj─ůc z getServerSideProps:

pages/users/[id].tsx
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();
  // UWAGA: obiekt `session` nie będzie miał stanu ładowania, ponieważ jest już pobrany na serwerze
  ...
}

Do┼é─ůczanie user.id do sesji

Create T3 App jest skonfigurowany tak, aby wykorzysta─ç callback sessionÔćŚ w konfiguracji NextAuth.js do dodania ID u┼╝ytkownika do obiektu session.

server/auth.ts
callbacks: {
    session({ session, user }) {
      if (session.user) {
        session.user.id = user.id;
      }
      return session;
    },
  },

┼ü─ůczy si─Ö to z plikiem deklaracji typ├│w, aby zapewni─ç odpowiednie typy obiektu session - musi on zawiera─ç powy┼╝sze pole user.id. Wi─Öcej o zmianie typ├│w poczyta─ç mo┼╝esz w rozdziale Module AugmentationÔćŚ dokumentacji NextAuth.js.

server/auth.ts
import { DefaultSession } from "next-auth";

declare module "next-auth" {
  interface Session {
    user?: {
      id: string;
    } & DefaultSession["user"];
  }
}

Ten sam spos├│b wykorzystany mo┼╝e zosta─ç do dodania wi─Ökszej ilo┼Ťci danych na obiekcie session, takich jak pole role (rola). Nie powinien by─ç on jednak wykorzystany do zapisywania wra┼╝liwych danych dla klienta.

Korzystanie wraz z tRPC

Je┼╝eli u┼╝ywasz NextAuth.js oraz tRPC, stworzy─ç mo┼╝na zabezpieczone procedury (z mo┼╝liwo┼Ťci─ů wielokrotnego u┼╝ycia) korzystaj─ůc z middlewareÔÇÖ├│wÔćŚ. Pozwala to na umieszczenie procedur, kt├│re zainicjowane by─ç mog─ů jedynie przez autoryzowanych u┼╝ytkownik├│w. create-t3-app wszystko to dla Ciebie konfiguruje, daj─ůc ci mo┼╝liwo┼Ť─ç ┼éatwego dost─Öpu do obiektu sesji w┼Ťr├│d autoryzowanych procedur.

Konfiguracja ta zachodzi w dw├│ch krokach:

  1. Pobierz sesj─Ö z header├│w zapytania korzystaj─ůc z funkcji getServerSessionÔćŚ. Zalet─ů korzystania z getServerSession zamiast getSession jest fakt, i┼╝ jest to funkcja wywo┼éywana jedynie po stronie serwera i nie inicjuje ona ┼╝adnych niepotrzebnych zapyta┼ä. create-t3-app tworzy funkcj─Ö pomocnicz─ů, kt├│ra u┼éatwia korzystanie z getServerSession - nie musisz wi─Öc importowa─ç zar├│wno opcji NextAuth.js jak i funkcji getServerSession za ka┼╝dym razem, kiedy chcesz otrzyma─ç sesj─Ö.
server/auth.ts
export const getServerAuthSession = (ctx: {
  req: GetServerSidePropsContext["req"];
  res: GetServerSidePropsContext["res"];
}) => {
  return getServerSession(ctx.req, ctx.res, authOptions);
};

Korzystaj─ůc z tej funkcji pomocniczej, mo┼╝emy otrzyma─ç sesj─Ö i przes┼éa─ç j─ů do kontekstu tRPC:

server/api/trpc.ts
import { getServerAuthSession } from "../common/get-server-auth-session";

export const createContext = async (opts: CreateNextContextOptions) => {
  const { req, res } = opts;
  const session = await getServerAuthSession({ req, res });
  return await createContextInner({
    session,
  });
};
  1. Stw├│rz middleware tRPC, kt├│ry sprawdza, czy u┼╝ytkownik jest autoryzowany. Wykorzystamy nast─Öpnie stworzony middleware w protectedProcedure - specjalnej, zabezpieczonej procedurze. Ka┼╝da osoba wywo┼éuj─ůca j─ů b─Ödzie musia┼éa spe┼énia─ç warunki autoryzacji - w przeciwnym razie wyst─ůpi b┼é─ůd, kt├│ry w odpowiedni spos├│b b─Ödzie m├│g┼é zosta─ç obs┼éu┼╝ony po stronie klienta.
server/api/trpc.ts
const isAuthed = t.middleware(({ ctx, next }) => {
  if (!ctx.session || !ctx.session.user) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  return next({
    ctx: {
      // `session` dziedzicz─ůca odpowiedni typ w tym przypadku nie mo┼╝e mie─ç warto┼Ťci `null`
      session: { ...ctx.session, user: ctx.session.user },
    },
  });
});

export const protectedProcedure = t.procedure.use(isAuthed);

Obiekt session to minimalna i lekka reprezentacja u┼╝ytkownika zawieraj─ůca jedynie par─Ö p├│l. Je┼Ťli korzystasz z procedur protectedProcedure, masz dost─Öp do ID u┼╝ytkownika, kt├│re mo┼╝e zosta─ç wykorzystane do pobrania wi─Ökszej ilo┼Ťci danych z bazy.

server/api/routers/user.ts
const userRouter = router({
  me: protectedProcedure.query(async ({ ctx }) => {
    const user = await prisma.user.findUnique({
      where: {
        id: ctx.session.user.id,
      },
    });
    return user;
  }),
});

Korzystanie wraz z Prism─ů

Przygotowanie NextAuth.js do pracy z Prism─ů wymaga wiele wst─Öpnej konfiguracjiÔćŚ. create-t3-app zajmuje si─Ö ni─ů za Ciebie, a je┼Ťli wybierzesz zar├│wno Prism─Ö i NextAuth.js, otrzymasz w pe┼éni dzia┼éaj─ůcy system uwierzytelniania, wraz z wszystkimi potrzebnymi modelami bazy danych. Szablon aplikacji, kt├│ry dostarczamy, zawiera domy┼Ťlnie provider OAuth Discorda, kt├│ry wybrali┼Ťmy z powodu bycia jednym z ┼éatwiejszych do obs┼éugiwania - jedyne, co musiz zrobi─ç, to poda─ç tokeny w pliku .envÔÇŽ i gotowe! Je┼╝eli jednak chcesz skorzysta─ç z czego┼Ť innego, mo┼╝esz w ┼éatwy spos├│b do┼é─ůczy─ç inne providery opieraj─ůc si─Ö na dokumentacji NextAuth.jsÔćŚ. Uwaga - niekt├│re z provider├│w wymagaj─ů wi─Ökszej ilo┼Ťci p├│l na modelach w bazie danych. Polecamy Ci przeczyta─ç dokumentacj─Ö providera, z kt├│rego chcia┼éby┼Ť skorzysta─ç aby upewni─ç si─Ö, i┼╝ posiadasz wszystko, czego potrzebujesz.

Dodawanie nowych p├│l do modeli

Kiedy dodajesz nowe pola do kt├│regokolwiek z modeli - User, Account, Session lub VerificationToken (prawdopodobnie b─Ödziesz chcia┼é zmienia─ç jedynie model User) - pami─Öta─ç musisz, i┼╝ adapter dla PrismyÔćŚ automatycznie tworzy pola na powy┼╝szych modelach w przypadku rejestracji kont i logowania na nie. Z tego te┼╝ powodu, dodaj─ůc nowe pola do tych┼╝e modeli, zaopatrzy─ç musisz je w warto┼Ťci domy┼Ťlne - adapter nie jest ich ┼Ťwiadomy.

Je┼╝eli przyk┼éadowo chcesz doda─ç pole role (roli) do modelu User (u┼╝ytkownika), musisz pami─Öta─ç o do┼é─ůczeniu warto┼Ťci domy┼Ťlnej tego pola. Zrobisz to za pomoc─ů warto┼Ťci @default w modelu User:

prisma/schema.prisma
+ enum Role {
+   USER
+   ADMIN
+ }

  model User {
    ...
+   role Role @default(USER)
  }

Korzystanie wraz z middlewarem Next.js

Wykorzystanie middlewareÔÇÖa Next.js wymaga od Ciebie skorzystania ze strategii JWTÔćŚ do autoryzacji. Dzieje si─Ö tak, poniewa┼╝ middleware jest w stanie pobiera─ç ciasteczko sesji jedynie, gdy jest ono JWT. Create T3 App jest skonfigurowany tak, by wykorzysta─ç domy┼Ťln─ů strategi─Ö bazy danych, wraz z Prism─ů jako jej adapterem.

Konfigurowanie domy┼Ťlnego providera Discord (DiscordProvider)

  1. Przejd┼║ do sekcji Aplikacje w Panelu Discord Developer PortalÔćŚ, a nast─Öpnie kliknij na ÔÇťNew ApplicationÔÇŁ
  2. W menu ustawie┼ä, przejd┼║ do ÔÇťOAuth2 => GeneralÔÇŁ
  • Skopiuj Client ID i wklej go do pliku .env pod kluczem DISCORD_CLIENT_ID.
  • Pod Client Secret, kliknij ÔÇťReset SecretÔÇŁ i skopiuj podany tekst do pliku .env pod kluczem DISCORD_CLIENT_SECRET. Uwa┼╝aj - nie b─Ödziesz m├│g┼é ponownie zobaczy─ç tego klucza, a jego reset spowoduje wyga┼Ťni─Öcie aktualnego.
  • Dodaj ÔÇťAdd RedirectÔÇŁ i wklej tam <app url>/api/auth/callback/discord (przyk┼éadowo dla lokalnej aplikacji: http://localhost:3000/api/auth/callback/discordÔćŚ)
  • Zapisz zmiany
  • Jest mo┼╝liwo┼Ť─ç (nie jest ona jednak polecana), aby wykorzysta─ç t─ů sam─ů aplikacj─Ö Discorda dla zar├│wno aplikacji lokalnej i tej w wersji produkcyjnej. Mo┼╝esz tak┼╝e wykorzysta─ç mockowanie provideraÔćŚ podczas rozwoju aplikacji.

Przydatne Zasoby

Zas├│bLink
Dokumentacja NextAuth.jshttps://next-auth.js.org/ÔćŚ
GitHub NextAuth.jshttps://github.com/nextauthjs/next-authÔćŚ
tRPC Kitchen Sink - wraz z NextAuthhttps://kitchen-sink.trpc.io/next-authÔćŚ