Autentizace React, zjednodušená

Autentizace je jedna z věcí, která prostě vždy vyžaduje mnohem více úsilí, než bychom chtěli. Chcete-li nastavit autentizaci, musíte znovu prozkoumat témata, o kterých jste od poslední autentizace nepřemýšleli, a rychlá povaha prostoru znamená, že se věci mezitím často změnily. Nové hrozby, nové možnosti a nové aktualizace vás možná donutily hádat a prohrabávat se dokumenty ve vašich minulých projektech.

V tomto článku popisujeme jiný přístup k autentizaci (a řízení přístupu, jednotné přihlašování a další) v aplikacích React. Spíše než přidávat statickou knihovnu, kterou musíte aktualizovat nebo znovu zkoumat pokaždé, když chcete implementovat ověřování, použijeme službu, která zůstane automaticky aktuální a je mnohem jednodušší alternativou k Auth0, Okta a ostatní.

Reagovat na ověření

Při psaní ověřování v Reactu obvykle používáme podobný přístup:naše aplikace React odešle požadavek našemu ověřovacímu serveru, který pak vrátí přístupový token. Tento token je uložen v prohlížeči a lze jej použít v následných požadavcích na váš server (nebo jiné servery, pokud je to potřeba). Ať už píšete standardní ověřování e-mailů a hesel nebo používáte magické odkazy nebo přihlášení pomocí jednotného přihlášení (SSO), jako je Google, Azure nebo Facebook, chceme, aby naše aplikace React odeslala počáteční požadavek na ověřovací server a aby tento server zvládl veškerou složitost generování tokenu.

Zodpovědnost Reactu při ověřování je tedy:

  1. Odeslat úvodní požadavek na ověřovací server
  2. Přijměte a uložte přístupový token
  3. Při každém dalším požadavku odešlete přístupový token na váš server

Přístupové tokeny JWT

JSON Web Tokeny (JWT) jsou kompaktní tokeny bezpečné pro URL, které lze použít k ověřování a řízení přístupu v aplikacích React. Každý JWT má jako „užitnou část“ jednoduchý objekt JSON a je podepsán tak, aby váš server mohl ověřit, že je datová část autentická. Příklad JWT by vypadal takto:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImF1dGhvcml6YXRpb24iOiJhZG1pbiJ9.f7iKN-xi24qrQ5NQtOe0jiriotT-rve3ru6sskbQXnA

Užitná zátěž pro tento token je střední část (oddělená tečkami):

eyJ1c2VySWQiOjEsImF1dGhvcml6YXRpb24iOiJhZG1pbiJ9

Užitnou zátěž JWT lze dekódovat z base64 a získat objekt JSON:

JSON.parse(atob("eyJ1c2VySWQiOjEsImF1dGhvcml6YXRpb24iOiJhZG1pbiJ9"));

// =>
{
  “userId”: 1,
  “authorization”: “admin”
}

Je důležité poznamenat, že toto užitečné zatížení je čitelné pro kohokoli s JWT, včetně vaší aplikace React nebo třetí strany.

Každý, kdo má JWT, si může přečíst jeho obsah. Platné JWT však může generovat pouze ověřovací server – vaše aplikace React, váš aplikační server nebo škodlivá třetí strana nemohou generovat platné JWT. Takže kromě čtení JWT musí váš server také ověřit, že JWT je autentické tím, že jej zkontroluje pomocí veřejného klíče. To umožňuje vašemu aplikačnímu serveru ověřit příchozí JWT a odmítnout všechny tokeny, které nebyly vytvořeny ověřovacím serverem nebo jejichž platnost vypršela.

Postup pro použití JWT v aplikaci React vypadá takto:

  1. Vaše aplikace React vyžaduje JWT, kdykoli se uživatel chce přihlásit.
  2. Ověřovací server vygeneruje JWT pomocí soukromého klíče a poté odešle JWT zpět do vaší aplikace React.
  3. Vaše aplikace React ukládá tento JWT a odesílá jej na váš aplikační server, kdykoli váš uživatel potřebuje zadat požadavek.
  4. Váš aplikační server ověří JWT pomocí veřejného klíče a poté přečte obsah, aby určil, který uživatel podává požadavek.

Každý z těchto kroků se snadno zapisuje, ale každý krok má svá vlastní úskalí, když jej skutečně chcete implementovat a udržet v bezpečí. Zejména v průběhu času, kdy se objevují nové vektory hrozeb a nové platformy je třeba opravovat nebo podporovat, může režie zabezpečení rychle narůstat.

Userfront odstraňuje složitost ověřování v aplikacích React

Userfront je rámec, který odstraňuje složitost ověřování. Díky tomu je pro vás mnohem snazší pracovat s autentizací v aplikaci React a co je možná nejdůležitější, všechny autentizační protokoly se pro vás v průběhu času automaticky aktualizují.

Základní filozofií Userfront je, že prvotřídní ověřování by nemělo vyžadovat úsilí – mělo by být snadné jej nastavit a aktualizace zabezpečení by se vám měly dít automaticky. Userfront má všechny zvonky a píšťalky autentizace, jednotného přihlášení (SSO), řízení přístupu a vícenásobného pronájmu s bezplatnou úrovní připravenou pro produkci až 10 000 aktivních uživatelů měsíčně. Pro většinu moderních aplikací React je to skvělé řešení.

Nastavení ověřování v Reactu

Nyní projdeme vytvořením všech hlavních aspektů autentizace v aplikaci React. Konečný kód pro tento příklad je k dispozici zde.

Použijte svůj oblíbený standard k nastavení aplikace React a dejte si do pořádku svůj build pipeline. V tomto článku použijeme aplikaci Create React, která za nás udělá spoustu práce s nastavením, a také přidáme React Router pro naše směrování na straně klienta. Začněte instalací Create React App a React Router:

npx create-react-app my-app
cd my-app
npm install react-router-dom --save
npm start

Nyní je naše aplikace React k dispozici na http://localhost:3000

Jak se říká, nyní můžeme upravit src/App.js soubor začít pracovat.

Nahraďte obsah src/App.js s následujícím na základě rychlého startu React Router:

// src/App.js

import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";

export default function App() {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/login">Login</Link>
            </li>
            <li>
              <Link to="/reset">Reset</Link>
            </li>
            <li>
              <Link to="/dashboard">Dashboard</Link>
            </li>
          </ul>
        </nav>

        <Switch>
          <Route path="/login">
            <Login />
          </Route>
          <Route path="/reset">
            <PasswordReset />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

function Home() {
  return <h2>Home</h2>;
}

function Login() {
  return <h2>Login</h2>;
}

function PasswordReset() {
  return <h2>Password Reset</h2>;
}

function Dashboard() {
  return <h2>Dashboard</h2>;
}

Nyní máme velmi jednoduchou aplikaci se směrováním:

Trasa Popis
/ Domovská stránka
/login Přihlašovací stránka
/reset Stránka pro resetování hesla
/dashboard Uživatelský panel, pouze pro přihlášené uživatele

Toto je celá struktura, kterou potřebujeme, abychom mohli začít přidávat autentizaci.

Registrace, přihlášení a resetování hesla pomocí Userfront

Nejprve si vytvořte účet Userfront na https://userfront.com. Získáte tak přihlašovací formulář, přihlašovací formulář a formulář pro resetování hesla, které můžete použít pro další kroky.

V sekci Toolkit na vašem panelu Userfront naleznete pokyny k instalaci registračního formuláře:

Postupujte podle pokynů a nainstalujte balíček reakce Userfront s:

npm install @userfront/react --save
npm start

Poté přidejte formulář na svou domovskou stránku importem a inicializací Userfront a poté aktualizací Home() funkce k vykreslení formuláře.

// src/App.js

import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import Userfront from "@userfront/react";

Userfront.init("demo1234");

const SignupForm = Userfront.build({
  toolId: "nkmbbm",
});

export default function App() {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/login">Login</Link>
            </li>
            <li>
              <Link to="/reset">Reset</Link>
            </li>
            <li>
              <Link to="/dashboard">Dashboard</Link>
            </li>
          </ul>
        </nav>

        <Switch>
          <Route path="/login">
            <Login />
          </Route>
          <Route path="/reset">
            <PasswordReset />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

function Home() {
  return (
    <div>
      <h2>Home</h2>
      <SignupForm />
    </div>
  );
}

function Login() {
  return <h2>Login</h2>;
}

function PasswordReset() {
  return <h2>Password Reset</h2>;
}

function Dashboard() {
  return <h2>Dashboard</h2>;
}

Nyní je na domovské stránce váš přihlašovací formulář. Zkuste zaregistrovat uživatele:

Formulář je ve výchozím nastavení v "Testovacím režimu", který vytvoří záznamy uživatelů v testovacím prostředí, které můžete zobrazit samostatně na řídicím panelu Userfront:

Pokračujte přidáním přihlašovacích formulářů a formulářů pro resetování hesla stejným způsobem, jakým jste přidali přihlašovací formulář:

// src/App.js

import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import Userfront from "@userfront/react";

Userfront.init("demo1234");

const SignupForm = Userfront.build({
  toolId: "nkmbbm",
});
const LoginForm = Userfront.build({
  toolId: "alnkkd",
});
const PasswordResetForm = Userfront.build({
  toolId: "dkbmmo",
});

export default function App() {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/login">Login</Link>
            </li>
            <li>
              <Link to="/reset">Reset</Link>
            </li>
            <li>
              <Link to="/dashboard">Dashboard</Link>
            </li>
          </ul>
        </nav>

        <Switch>
          <Route path="/login">
            <Login />
          </Route>
          <Route path="/reset">
            <PasswordReset />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

function Home() {
  return (
    <div>
      <h2>Home</h2>
      <SignupForm />
    </div>
  );
}

function Login() {
  return (
    <div>
      <h2>Login</h2>
      <LoginForm />
    </div>
  );
}

function PasswordReset() {
  return (
    <div>
      <h2>Password Reset</h2>
      <PasswordResetForm />
    </div>
  );
}

function Dashboard() {
  return <h2>Dashboard</h2>;
}

V tomto okamžiku by vaše registrace, přihlášení a resetování hesla měly být funkční.

Vaši uživatelé se mohou zaregistrovat, přihlásit a resetovat své heslo.

Chráněná trasa v Reactu

Obvykle nechceme, aby uživatelé mohli prohlížet řídicí panel, pokud nejsou přihlášeni. Tomu se říká ochrana trasy.

Kdykoli uživatel není přihlášen, ale pokouší se navštívit /dashboard , můžeme je přesměrovat na přihlašovací obrazovku.

Můžeme toho dosáhnout aktualizací Dashboard komponenta v src/App.js zvládnout podmíněnou logiku.

Když je uživatel přihlášen pomocí Userfront, bude mít k dispozici přístupový token jako Userfront.accessToken() . Můžeme zkontrolovat tento token, abychom zjistili, zda je uživatel přihlášen.

Přidejte Redirect komponentu na import pro React Router a poté aktualizujte Dashboard komponenta k přesměrování, pokud není přítomen žádný přístupový token.

// src/App.js

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  Redirect, // Be sure to add this import
} from "react-router-dom";

// ...

function Dashboard() {
  function renderFn({ location }) {
    // If the user is not logged in, redirect to login
    if (!Userfront.accessToken()) {
      return (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: location },
          }}
        />
      );
    }

    // If the user is logged in, show the dashboard
    const userData = JSON.stringify(Userfront.user, null, 2);
    return (
      <div>
        <h2>Dashboard</h2>
        <pre>{userData}</pre>
        <button onClick={Userfront.logout}>Logout</button>
      </div>
    );
  }

  return <Route render={renderFn} />;
}

Všimněte si také, že jsme přidali tlačítko pro odhlášení voláním Userfront.logout() přímo:

<button onClick={Userfront.logout}>Logout</button>

Nyní, když je uživatel přihlášen, může zobrazit řídicí panel. Pokud uživatel není přihlášen, bude přesměrován na přihlašovací stránku.

Reagovat na ověřování pomocí rozhraní API

Pravděpodobně budete chtít získat informace specifické pro uživatele z vašeho backendu. Za účelem ochrany těchto koncových bodů API by váš server měl zkontrolovat, zda jsou příchozí JWT platné.

Existuje mnoho knihoven pro čtení a ověřování JWT v různých jazycích; zde je několik oblíbených knihoven pro práci s JWT:

Node.js .NET Python Java

Pro Userfront je přístupový token k dispozici ve vaší aplikaci React jako Userfront.accessToken() .

Vaše aplikace React to může odeslat jako Bearer token uvnitř Authorization záhlaví. Například:

// Example of calling an endpoint with a JWT

async function getInfo() {
  const res = await window.fetch("/your-endpoint", {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${Userfront.accessToken()}`,
    },
  });

  console.log(res);
}

getInfo();

Aby bylo možné takový požadavek zpracovat, měl by váš backend přečíst JWT z Authorization záhlaví a ověřte, že je platný pomocí veřejného klíče, který najdete na řídicím panelu Userfront.

Zde je příklad middlewaru Node.js ke čtení a ověření JWT:

// Node.js example (Express.js) 
const jwt = require("jsonwebtoken"); 

function authenticateToken(req, res, next) {   
    // Read the JWT access token from the request header
    const authHeader = req.headers["authorization"];
    const token = authHeader && authHeader.split(" ")[1];
    if (token == null) return res.sendStatus(401); 
    // Return 401 if no token   
    // Verify the token using the Userfront public key   
    jwt.verify(token, process.env.USERFRONT_PUBLIC_KEY, (err, auth) => {     
        if (err) return res.sendStatus(403); // Return 403 if there is an error verifying
        req.auth = auth;
        next();
    }); 
}

Při použití tohoto přístupu budou všechny neplatné nebo chybějící tokeny vaším serverem odmítnuty. Na obsah tokenu můžete také odkazovat později v obslužných rutinách trasy pomocí req.auth objekt:

console.log(req.auth);

// =>
{
  mode: 'test',
  tenantId: 'demo1234',
  userId: 1,
  userUuid: 'ab53dbdc-bb1a-4d4d-9edf-683a6ca3f609',
  isConfirmed: false,
  authorization: {
    demo1234: {
      tenantId: 'demo1234',
      name: 'Demo project',
      roles: ["admin"],
      permissions: []
    },
  },
  sessionId: '35d0bf4a-912c-4429-9886-cd65a4844a4f',
  iat: 1614114057,
  exp: 1616706057
}

S těmito informacemi můžete podle potřeby provádět další kontroly nebo použít userId nebo userUuid vyhledat informace o uživateli, které chcete vrátit.

Pokud jste například chtěli omezit cestu na uživatele s oprávněním správce, můžete zkontrolovat authorization objekt z ověřeného přístupového tokenu:

// Node.js example (Express.js)

app.get("/users", (req, res) => {
  const authorization = req.auth.authorization["demo1234"] || {};

  if (authorization.roles.includes("admin")) {
    // Allow access
  } else {
    // Deny access
  }
});

React SSO (Single Sign On)

Odtud můžete do aplikace React přidat poskytovatele sociální identity, jako je Google, Facebook a LinkedIn, nebo poskytovatele firemní identity, jako je Azure AD, Office365 a další.

Uděláte to tak, že vytvoříte aplikaci u poskytovatele identity (např. Google) a poté přidáte přihlašovací údaje této aplikace na řídicí panel Userfront. Výsledkem je upravená zkušenost s přihlášením:

K implementaci jednotného přihlášení pomocí tohoto přístupu není potřeba žádný další kód:můžete přidávat a odebírat poskytovatele, aniž byste aktualizovali své formuláře nebo způsob, jakým zacházíte s JWT.

Závěrečné poznámky

Přidání ověřování a řízení přístupu do vaší aplikace React nemusí být problém. Jak krok nastavení, tak, což je důležitější, údržba v průběhu času, jsou řešeny pomocí moderních platforem, jako je Userfront.

Webové tokeny JSON vám umožňují čistě oddělit vrstvu generování autentizačního tokenu od zbytku vaší aplikace, což usnadňuje uvažování a je modulárnější pro budoucí potřeby. Tato architektura vám také umožňuje zaměřit vaše úsilí na vaši hlavní aplikaci, kde pravděpodobně vytvoříte mnohem větší hodnotu pro sebe nebo své klienty.

Další podrobnosti o přidávání ověření do vaší aplikace React najdete v průvodci Userfront, který pokrývá vše od nastavení formulářů pro ověření po dokumentaci API, ukázkové repozitáře, práci s různými jazyky a frameworky a další.

Vytvořte bezplatný projekt Userfront

Sponzorováno prostřednictvím Syndicate