Integrujte SuperTokens Passwordless Authentication s Next.js

Rychlý úvod

Authentication je mechanismus pro ověření identity uživatele pro aplikaci. Autentizace uživatele pomocí userId a hesla je nejběžnějším mechanismem, který používáme v mnoha aplikacích. Existují však i další slavné přístupy. Můžeme ověřovat uživatele pomocí sociálních přihlášení, jednorázových hesel (OTP) nebo magického odkazu, který pomáhá s přímou autentizací.

SuperTokens je open source, vysoce přizpůsobený rámec poskytovatele autentizace uživatelů, který pomáhá se všemi těmito formami autentizačních mechanismů pro vaše webové aplikace. Je přímočará integrace s back-end frameworkem, jako je NodeJS, GoLang, Python a front-endová strana s ReactJS, React Native, Plain Old JavaScript.

Next.js je populární framework React pro vytváření rychlých webových aplikací. V tomto článku se naučíme, jak integrovat sílu autentizačního mechanismu SuperTokens s aplikacemi Next.js. Zaměříme se na passwordless autentizace, ale další recepty, jako je používání sociálních přihlášení nebo userId/password, budou podobné.

Co dnes stavíme?

Začneme jednoduchou, ale účinnou aplikací Next.js a integrujeme do ní sílu SuperTokenů. Aplikace se nazývá Retell , který ukazuje slavné citáty slavných lidí z celého světa. Otevřete svůj oblíbený editor kódu a postupujte podle tohoto článku. Užijte si její budování.

Kdykoli, pokud se chcete odkázat na zdrojový kód, můžete jej najít zde:

https://github.com/atapas/quotes

Pokud se vám práce líbila, dejte ⭐ repo. Motivuje mě to.

Nastavení Retell Uživatelské rozhraní projektu

Tento článek předpokládá, že máte základní znalosti o React.js a umíte se řídit zdrojovým kódem Next.js. Chcete-li spustit Retell, postupujte podle těchto kroků uživatelské rozhraní projektu lokálně,

  • Fork nebo klonování tohoto úložiště:https://github.com/atapas/quotes
  • Přepnout na uživatelské rozhraní pouze pro větev
  • Nainstalujte závislosti pomocí tohoto příkazu z terminálu

    npm install
    # or
    yarn
    
  • Potom spusťte vývojový server

    npm run dev
    # or
    yarn dev
    

    Nyní otevřete aplikaci pomocí adresy URL http://localhost:3000, abyste viděli úspěšně vykreslené uvozovky.

Můžete také vstoupit do quotes API pomocí adresy URL:http://localhost:3000/api/quotes

Gratulujeme!!! Spustili jste uživatelské rozhraní. Pojďme s ním nyní integrovat SuperTokens Passwordless auth.

Nastavení ověření SuperTokens

SuperTokens Recept na autentizaci bez hesla vám pomůže ověřit pomocí OTP (jednorázových hesel) a magických odkazů. Tento typ ověření nakonfigurujeme pomocí naší aplikace Next.js v několika krocích

  • Vytvořte konfiguraci front-end a back-end.
  • Zobrazit přihlašovací uživatelské rozhraní
  • Přidat rozhraní API pro ověření
  • Chraňte trasy webových stránek
  • Proveďte ověření relace u volání API

Pro všechny výše uvedené kroky musíme nainstalovat několik závislostí. Nainstalujte prosím závislosti pomocí následujícího příkazu

yarn add supertokens-auth-react supertokens-node dotenv  nodemailer

Konfigurace front-end a back-end

Vytvořte .env.local soubor v kořenovém adresáři projektu s následujícím obsahem,

NEXT_PUBLIC_NODEMAILER_USER=<YOUR_GMAIL_ID>
NEXT_PUBLIC_NODEMAILER_PASSWORD=<YOUR_GMAIL_PASSWORD>

NEXT_PUBLIC_APP_URL=http://localhost:3000

Vytvořte config složku v kořenovém adresáři vašeho projektu. Nyní vytvořte appInfo.js uvnitř config složku s následujícím obsahem,

const port = process.env.APP_PORT || 3000

const apiBasePath = '/api/auth/'

export const websiteDomain =
  process.env.APP_URL ||
  process.env.NEXT_PUBLIC_APP_URL ||
  `http://localhost:${port}`

export const appInfo = {
  appName: 'Retell',
  websiteDomain,
  apiDomain: websiteDomain,
  apiBasePath,
}

appInfo.js obsahuje speciální objekt, který určuje proměnné pro konfiguraci front-end a back-end. Přečtěte si prosím více o appInfo objekt odtud.

Dále vytvořte frontendConfig.js soubor uvnitř config složku s následujícím obsahem,

import PasswordlessReact from "supertokens-auth-react/recipe/passwordless";
import SessionReact from "supertokens-auth-react/recipe/session";
import { appInfo } from "./appInfo";

export const frontendConfig = () => {
  return {
    appInfo,
    recipeList: [
      PasswordlessReact.init({
        contactMethod: "EMAIL_OR_PHONE",
      }),
      SessionReact.init(),
    ],
  };
};

Zde vytvoříme funkci, která poskytne konfiguraci pro front-end SDK SuperTokens. Později uvidíme, jak tuto funkci používat. Vezměte prosím na vědomí, že způsob kontaktu je EMAIL_OR_PHONE . To znamená, že ověření bez hesla proběhne odesláním OTP a magického odkazu na e-mail nebo telefonní číslo, které uživatel zadá pro přihlášení.

Nyní vytvoříme konfigurace back-endu. Vytvořte prosím soubor s názvem backendConfig.js uvnitř config složku s následujícím obsahem,

require("dotenv").config();

import Session from "supertokens-auth-react/recipe/session";
import PasswordlessNode from "supertokens-node/recipe/passwordless";
import SessionNode from "supertokens-node/recipe/session";
import { appInfo } from "./appInfo";
let { getEmailBody } = require("../util/mailer");

export const backendConfig = () => {
  const nodemailer = require('nodemailer');

  const mailTransporter = nodemailer.createTransport({
    host: "smtp.gmail.com",
    port: 465,
    secure: true,
    auth: {
        user: process.env.NEXT_PUBLIC_NODEMAILER_USER,
        pass: process.env.NEXT_PUBLIC_NODEMAILER_PASSWORD,
    },
  });

  return {
    framework: "express",
    supertokens: {
      connectionURI: "https://try.supertokens.com",
      // apiKey: "IF YOU HAVE AN API KEY FOR THE CORE, ADD IT HERE",
    },
    appInfo,
    recipeList: [
      PasswordlessNode.init({
        flowType: "USER_INPUT_CODE_AND_MAGIC_LINK",
        contactMethod: "EMAIL_OR_PHONE",
        createAndSendCustomEmail: async (input, context) => {
          try{
            let htmlBody = getEmailBody(
              appInfo.appName,
              Math.ceil(input.codeLifetime / 1000),
              input.urlWithLinkCode,
              input.userInputCode,
              input.email
            );
            await mailTransporter.sendMail({
              html: htmlBody,
              to: input.email,
              from: `Team Supertokens <${appInfo.appName}>`,
              sender: process.env.NEXT_PUBLIC_NODEMAILER_USER,
              subject: `Login to ${appInfo.appName}`,
            });
          } catch (err) {
            console.log(err);
          }
        },
        createAndSendCustomTextMessage: async (input, context) => {
          // Creating a Twilio account and set it up.
        },
      }),
      SessionNode.init(),
    ],
    isInServerlessEnv: true,
  };
};

Použili jsme try.supertokens.com jako connectionURI hodnotu výše. Všimněte si prosím URI try.supertokens.com slouží pro demo účely. Musíte si nastavit vlastní jádro a nahradit adresu jádra výše.

Vlastní jádro můžete nastavit dvěma způsoby,

  • By self-hosting SuperTokens :Jádro SuperTokens můžete hostovat sami pomocí své vlastní databáze (MySQL nebo PostgreSQL). Samostatně hostovat můžete buď ruční instalaci SuperTokenů, nebo prostřednictvím dockeru.
  • By using the managed service option :Chcete-li nastavit jádro SuperTokens na spravované službě, vytvořte si bezplatný účet a přihlaste se. Dále vytvořte novou aplikaci z řídicího panelu. Po dokončení naleznete connectionURI a API klíč na stránce s podrobnostmi o aplikaci.

Dobře, nyní si promluvme o dvou způsobech doručení, které jsme uvedli v kódu výše:

  • createAndSendCustomEmail :Jedná se o způsob doručování založený na e-mailu, který využívá přihlašovací údaje Gmailu z proměnných prostředí. Upozorňujeme, že používáme getEmailBody() způsob formátování e-mailové zprávy.

    Vytvořte prosím složku s názvem util v kořenovém adresáři složky projektu. Nyní vytvořte soubor s názvem mailer.js který exportuje getEmailBody() metoda. Zde je ukázková implementace souboru mailer.js. Můžete zkopírovat a vložit celý obsah.

  • createAndSendCustomTextMessage :Je to metoda doručování založená na SMS. Můžete si vytvořit účet Twilio a nastavit jej pomocí několika jednoduchých kroků. Zde můžete najít jeho příklad.

Více o atributech způsobu doručení naleznete zde.

Nyní zavoláme front-endové init funkce z _app.js soubor. Otevřete prosím _app.js soubor pod pages složku a nahraďte obsah následujícím,

import React from 'react'
import SuperTokensReact from 'supertokens-auth-react'
import { frontendConfig } from '../config/frontendConfig'
import '../styles/globals.css'


if (typeof window !== 'undefined') {
  // we only want to call this init function on the frontend, so 
  // we check typeof window !== 'undefined'
  SuperTokensReact.init(frontendConfig())
}

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp

Nyní jsme tedy se všemi konfiguracemi hotovi. Nyní si ukážeme přihlašovací uživatelské rozhraní.

Zobrazit přihlašovací uživatelské rozhraní

Vytvořte prosím auth složky uvnitř pages složku. Nyní vytvořte [[...path]].js soubor uvnitř auth/pages složku s následujícím obsahem,

import dynamic from 'next/dynamic'
import React, { useEffect } from 'react'
import SuperTokens from 'supertokens-auth-react'
import { redirectToAuth } from 'supertokens-auth-react/recipe/passwordless'

const SuperTokensComponentNoSSR = dynamic(
  new Promise((res) => res(SuperTokens.getRoutingComponent)),
  { ssr: false }
)

export default function Auth() {

  // if the user visits a page that is not handled by us (like /auth/random), 
  // then we redirect them back to the auth page.
  useEffect(() => {
    if (SuperTokens.canHandleRoute() === false) {
      redirectToAuth()
    }
  }, [])

  return (
      <SuperTokensComponentNoSSR />
  )
}

Je to naše komponenta Auth. Dobře, pojďme to otestovat. Otevřete kartu prohlížeče a otevřete /auth aplikace URL, http://localhost:3000/auth. V této fázi byste měli vidět přihlašovací uživatelské rozhraní.

Hlavní stránka aplikace (localhost:3000) a rozhraní API pro uvozovky (localhost:3000/api/quotes) stále nejsou chráněny pomocí Auth. Pojďme je udělat jeden po druhém.

Přidat rozhraní API pro ověření

Nyní přidáme všechna backendová rozhraní API pro ověřování na /api/auth . Vytvořte prosím auth složku v pages/api/ složku. Nyní vytvořte soubor [[...path]].js s následujícím obsahem,

require("dotenv").config();
import supertokens from 'supertokens-node';
import { middleware } from 'supertokens-node/framework/express';
import { superTokensNextWrapper } from 'supertokens-node/nextjs';
import { backendConfig } from '../../../config/backendConfig';

supertokens.init(backendConfig())

export default async function superTokens(req, res) {

  await superTokensNextWrapper(
    async (next) => {
      await middleware()(req, res, next)
    },
    req,
    res
  )
  if (!res.writableEnded) {
    res.status(404).send('Not found')
  }
}

[[...path]].js používá middleware vystavený supertokens-node , která odhaluje všechna rozhraní API, jako je přihlášení, registrace atd.

Nyní aktualizujte quotes API mít pouze autorizovaný přístup. Aktualizujte prosím obsah quotes.js soubor s následujícím obsahem,

import supertokens from 'supertokens-node';
import { superTokensNextWrapper } from 'supertokens-node/nextjs';
import { verifySession } from 'supertokens-node/recipe/session/framework/express';
import { backendConfig } from '../../config/backendConfig';
import quoteList from '../../data/quotes.json';

supertokens.init(backendConfig())

export default async function quotes(req, res) {
  await superTokensNextWrapper(
    async (next) => {
      return await verifySession()(req, res, next)
    },
    req,
    res
  )

  return res.json(quoteList.quotes)
}

Nyní otevřete rozhraní API pro uvozovky, http://localhost:3000/api/quotes. Uvidíte neoprávněnou chybu.

Nebojte se. Nyní opravíme celý pracovní postup.

Chránit trasy

Aby vše fungovalo, chraňme trasy. Otevřete prosím index.js soubor pod pages složku a nahraďte obsah následujícím obsahem,

import dynamic from 'next/dynamic';
import Head from 'next/head';
import React from 'react';
import Passwordless from "supertokens-auth-react/recipe/passwordless";
import supertokensNode from 'supertokens-node';
import Session from 'supertokens-node/recipe/session';
import Footer from '../components/Footer';
import Header from '../components/Header';
import QuoteList from '../components/QuoteList';
import styles from '../styles/Home.module.css';

const PasswordlessAuthNoSSR = dynamic(
  new Promise((res) =>
    res(Passwordless.PasswordlessAuth)
  ),
  { ssr: false }
)

export default function Home(props) {
  return (
    <PasswordlessAuthNoSSR>
      <ProtectedPage />
    </PasswordlessAuthNoSSR>
  )
}

function ProtectedPage({ userId }) {
  async function logoutClicked() {
    await Passwordless.signOut()
    Passwordless.redirectToAuth()
  }

  return (
    <div className={styles.container}>
      <Head>
        <title>Retell</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <Header />
      <main className={styles.main}>
        <QuoteList />
      </main>
      <Footer />
    </div>
  )
}

A je to. Přistupujete k aplikaci nebo rozhraní API pro uvozovky a přihlašovací stránka chrání obojí. Před přístupem k cenám musíte zadat své telefonní číslo nebo e-mailovou adresu, abyste získali jednorázové heslo a autorizovali se.

Úkol pro vás

Dobře, malý úkol pro vás. Můžete implementovat funkci odhlášení? V index.js máte funkci nazvanou logoutClicked() . Co takhle vyvolat metodu, když někdo klikne na Sign Out odkaz v záhlaví? Zkuste to prosím!

Ještě jednou, celý zdrojový kód je k dispozici zde na mém GitHubu:https://github.com/atapas/quotes. Pokud se po tomto článku setkáte s nějakými problémy nebo chybami při implementaci pracovního postupu, obraťte se na SuperTokens on Discord.

Než skončíme...

To je prozatím vše. Doufám, že jste našli tento článek srozumitelný.

Sdílím své znalosti na,

  • 🌐 Vývoj webu (JavaScript, ReactJS, Next.js, Node.js, atd...)
  • 🛡️ Webová bezpečnost
  • 💼 Kariérní rozvoj
  • 🌱 Opensource
  • ✍️ Vytváření obsahu

Pojďme se připojit,

  • Dejte sledovat na Twitteru
  • Přihlaste se k odběru mého kanálu YouTube
  • Vedlejší projekty na GitHubu
  • Komunita Showwcase React