web-dev-qa-db-fra.com

Next.js Example Auth - réacheminement basé sur auth, enveloppant d'autres fonctions

J'essaye d'utiliser le next.js avec l'authentification pour un petit projet. L'authentification fonctionne actuellement mais ne me permet pas d'afficher les données dans ma barre de navigation.

Je l'utilisais avec Firebase à l'origine MAIS PAS PLUS !! Maintenant, configurez l'authentification séparément ci-dessous.

Ceci est l'exemple de dépôt, il contient mon API pour auth et next.js, que j'essaie d'intégrer ensemble pour que la connexion et la déconnexion fonctionnent avec le jeu d'en-tête pour les appels API.

https://github.com/Hewlbern/example

Simplement obtenir la fonctionnalité de base de connexion et de déconnexion, afin que je puisse contrôler l'accès des utilisateurs à mon site Web. Je sais que c'est vraiment simple - juste assez confus comment le faire avec next.js avec le fonctionnement de la page de document d'une application: S

J'essaie de montrer un tableau de sortie de cette API et de donner la possibilité de télécharger le json produit (dans un CSV ou autre). Donc, avoir cela disponible après une recherche avec les paramètres de requête, et uniquement sur une page après que l'utilisateur est connecté, est le point :)

Voici un exemple de la fonctionnalité de connexion que j'utilise.

import { useRef, useState } from 'react';
import React from 'react'
import PropTypes from 'prop-types'

import Layout from "../components/Layout";




export default function Login() {
  const emailRef = useRef<HTMLInputElement>(null);
  const passRef = useRef<HTMLInputElement>(null);
  const [message, setMessage] = useState<any>(null);
  async function handleLogin() {
    const resp = await fetch('http://localhost:3001/auth/login', {
      method: 'POST',
      headers: {
        'Content-Type': "application/x-www-form-urlencoded"
      },
      body: JSON.stringify({
        email: emailRef.current?.value,
        password: passRef.current?.value
      })
    });
    const json = await resp.json();
    setMessage(json);
  }

  return (
    <Layout>
      {JSON.stringify(message)}
      <input type="text" placeholder="email" ref={emailRef} />
      <input type="password" placeholder="password" ref={passRef} />
      <button onClick={handleLogin}>Login</button>
    </Layout>
  );
}

Ceci est en train de poster sur cette demande d'API

router.post('/login', (req, res) => {

// console.log(req.body)

    let email = req.body.email;
    let password = req.body.password;

    console.log(email,password)

    DatabaseService.GetUser(email).then(user => {
            if(user===null){
                res.sendStatus(404);
            }
            else{
                if(bcrypt.compareSync(password, user[0].password)) {
                    jwt.sign({user}, 'secretkey', { expiresIn: '30d' }, (err, token) => {
                        DatabaseService.SetSession(token,JSON.stringify(user[0].user_id)).then(inserted=>{
                            res.json({
                                token
                            });
                        });
                    });
                } else {
                    res.sendStatus(500);
                }
            }
        });
});

Donc, juste avec ce petit exemple, quel est le problème avec la façon dont j'envoie les demandes actuellement? (en pensant que c'est le format dans lequel la connexion accepte les demandes?)

Si quelqu'un a fait quelque chose de similaire ou sait comment résoudre ces problèmes, je l'apprécierais vraiment :)

À votre santé!

7
Michael Holborn

Ce que je recommanderais ici est de créer un hook personnalisé qui utilise l'API contextuelle de React afin de "surveiller" le changement d'état d'authentification. Ensuite, enveloppez votre application dans ce fournisseur et vous aurez la possibilité de faire tout ce que vous voulez avec cet état d'authentification à l'aide de votre nouveau hook personnalisé.

Voici un exemple de l'apparence de ce hook personnalisé en utilisant une authentification avec Firebase:

import React, { createContext, useContext, useState } from 'react'

import { auth } from './services' // this is just firebase.auth()

const UserContext = createContext()

export const UserProvider = ({ children }) => {
  const [user, setUser] = useState(undefined)

  auth.onAuthStateChanged(setUser)

  return <UserContext.Provider value={user}>{children}</UserContext.Provider>
}

export const useUser = () => useContext(UserContext)

Il vous suffit maintenant d'encapsuler votre application dans le UserProvider.

Comme ça:

import React, { StrictMode } from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom'

import App from './app'
import { UserProvider } from './hooks'

const rootElement = document.getElementById('root')
ReactDOM.render(
  <StrictMode>
    <BrowserRouter>
      <UserProvider>
        <App />
      </UserProvider>
    </BrowserRouter>
  </StrictMode>,
  rootElement
)

Ensuite, à titre d'exemple, disons que vous vouliez vous éloigner automatiquement de votre page de connexion si l'utilisation est enregistrée. Vous pouvez utiliser les hooks useEffect et useHistory pour accéder à / si l'utilisateur est connecté.

Quelque chose comme ça va faire:

import React, { useEffect } from 'react'
import { useHistory } from 'react-router-dom'

import { useUser } from './hooks'

const LoginPage = () => {
  const history = useHistory()
  const user = useUser() // user is undefined if not logged in

  useEffect(() => {
    if (user) { // will run the condition if user exists
      history.Push('/')
    }

  }, [user])

  ...
}

Vous pouvez continuer à utiliser les données user dans votre barre de navigation en utilisant quelque chose comme ceci:

import React from 'react'
import { Link } from 'react-router-dom'

import { useUser } from './hooks'

const NavBar = () => {
  const user = useUser()

  return (
    <div>
      {user ?
        <Link to="/profile">Welcome, {user.displayName}</Link> :
        <Link to="/login">Login</Link>
      }
    </div>
  )
}

Évidemment, vous pouvez changer cela pour nous en fonction de vos propres besoins, mais tout cela devrait vous permettre de travailler avec l'état d'authentification de manière propre et robuste.

3