NodeJS + Express + VueJS : Authentication ?

a marqué ce sujet comme résolu.

Bonjour ! :)

Je me suis mis recemment à NodeJS et VueJS. J’aimais beaucoup… jusqu’à ce que j’arrache tout mes cheveux, que je casse 3 ordinateurs et que j’ai insulté tout mes voisins (rien que ça :D ). La raison ? Le système d’authentification.

Je ne comprend absolument rien du tout. Les tutos sur internet montre tous des méthodes différentes, et je suis complètement perdu.

Aujourd’hui, j’ai créé un petit blog très simple avec :

  • Backend :
    • NodeJS
    • ExpressJS
    • Cors
    • BodyParser
    • mysql
    • Sequelize
  • Frontend :
    • VueJS
    • Axios
    • Vue Axios
    • Vue Router

Mon projet est rangé comme ceci :

  • Projet (Frontend)
    • public/
    • src/
      • assets/
      • components/
        • LoginComponent.vue
        • DashboardComponent.vue
        • […]
      • App.vue
      • main.js
    • api/ (Backend avec NodeJS + Express)
    • [fichiers…]

Mon serveur est sur http://localhost:3000/ et la partie frontend avec VueJS est sur http://localhost:8080/ .

J’aimerais mettre en place un système d’authentification qui fontionne si le back et front sont pas sur le même serveur, mais aussi si ils sont sur le même serveur (j’ai cru comprendre que je pouvais faire un npm run build sur VueJS et l’intégré dans la backend après).

Avez-vous des tutoriels à me proposer ? Je voudrais ce qu’il y à de plus simple possible à mettre en place, n’étant vraiment pas du tout à l’aise avec ces technos là.

Pouvez-vous me dire de quoi j’ai besoin ? Parce qu’entre jwt, vue-auth, passport, vue-session, cookie-session, et j’en passe, je suis complètement perdu.

Merci ! :)

Edit : J’en profite aussi pour vous demander pourquoi quand je fait npm run serve sur VueJS et que je change un truc dans mon code, je suis obligé de faire CTRL+C et relancer la commande pour appliquer les changement ? Idem avec NodeJS quand je fait nodemon le serveur ne se recharge pas tout seul… alors qu’avant oui. C’est pénible.

+0 -0

Salut,

Un tuto qui se base sur JWT est disponible sur Scotch.io.

Concernant, le back, tu n’as pas besoin du module bodyParser, tu peux utiliser les 2 fonctions natives d’Express ci-dessous.

app.use(express.json()) // Activation du raw (json)
app.use(express.urlencoded({ extended: true })) // Activation de x-wwww-form-urlencoded

Source : https://expressjs.com

+0 -0

Merci pour vos réponses ! :)

Alors pendant que vous me répondiez, j’ai continuer et j’ai réussi.

J’ai utilisé axios et passport. Au départ, je recevais une réponse "Logged in" mais, lorsque je changeais de page, j’était constament déconnecté.

Après de nombreuse recherche et mes derniers cheuveux perdu, j’ai vu qu’il fallait faire deux choses :

  • Indiquer credentials et origin dans le app.use(cors).
  • Utiliser withCredentials = true dans axios en faisant axios.defaults.withCredentials = true.

Et là ça fonctionne. Cependant, j’aimerais comprendre pourquoi il fait faire ça. C’est écrit nul part dans aucune doc (que ce soit axios ou passport).

@EtienneR : Je ne savais pas pour body-parser. En fait, j’ai suivis le premier tuto trouvé sur le net pour faire un CRUD avec NodeJS et VueJS, et il fallait installer body-parser.

Mais de toute façon, j’ai jamais bien compris ce qu’était body-parser et à quoi il sert. Il me semble que c’est pour pouvoir récupérer des données de type POST ?

+0 -0

Je rajoute un petit message :

J’ai mon système de connexion/déconnexion qui fonctionne. Pour cela, j’utilise passport/express/express-session côté serveur, et axios/vue-router côté front.

Cependant, j’aimerais faire des routes protégés (require d’être connecté ou d’être admin).

Pour cela, j’ai créer une route /users/user dans le backend qui me retourne l’utilisateur actuel, ou un tableau vide si il n’est pas connecté.

Côté frontend, j’ai donc fait ceci qui fonctionne très bien :

var router = new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/login',
      name: 'Login',
      component: Login,
      meta: {
        requireLoggedIn: false
      }
    },
    {
      path: '/dashboard',
      name: 'Dashboard',
      component: Dashboard,
      meta: {
        requireLoggedIn: true
      }
    }
  ]
})

router.beforeEach((to, from, next) => {
  if ('requireLoggedIn' in to.meta) {
    axios.get('http://localhost:3000/users/user', {
      withCredentials: true
    })
      .then((response) => {
        var isLoggedIn = false
        var requireLoggedIn = to.meta.requireLoggedIn

        if (response.data.user) {
          isLoggedIn = true
        }

        if (requireLoggedIn === true && isLoggedIn === true) {
          return next()
        } else if (requireLoggedIn === true) {
          return next('/login')
        } else if (requireLoggedIn === false && isLoggedIn === false) {
          return next()
        } else if (requireLoggedIn === false) {
          return next('/')
        } else {
          return next()
        }
      })
      .catch(() => {
        var requireLoggedIn = to.meta.requiredLoggedIn

        if (requireLoggedIn === true) {
          return next('/login')
        } else if (requireLoggedIn === false) {
          return next('/')
        }
      })
  }

  return next()
})

Mais je me demande si, avec les modules que j’ai utilisé, il n’y à pas un meilleur moyen de faire ça (et moins manuel). J’ai entendu parler de Vuex qui permet de sauvegarder des etats, mais je ne sais pas si ça peut m’aider ou pas.

J’aurais bien stocké l’utilisateur dans une session avec VueJS (je crois qu’il y à un module vue-session pour ça), mais n’y à t-il pas besoin de vérifier à chaque fois que l’utilisateur est bien connecté ? Ou que l’utilisateur n’ai pas été modifié ?

Edit : Et j’ai pas compris l’utilité d’un Token avec JWT.

Je veux me connecter : Le front envois au back les identifiants et le backend va vérifier si ils sont bons. Si oui, il génère un token et le renvois au front, en plus de l’utilisateur. Je sauvegarde donc ces deux données dans le front dans une session (ou avec vuex). Mais ce Token, il sert à quoi ? Je veux dire, si je recois du back l’utilisateur, c’est qu’il est connecté, il me sert à quoi ce token ?

+0 -0

Comment tu les intègre sans agios ? Je ne savais pas que c’était possible et tout les tutoriels montre avec l’utilisation d’axios

Sinon j’ai build vuejs et je l’ai intégré à nododejs mais je n’arrive pas à mettre mon application en ligne… quand même, ces technos sont ultra dur à maîtriser et utiliser… beaucoup plus que php.

+0 -0

Comment tu les intègre sans agios ? Je ne savais pas que c’était possible et tout les tutoriels montre avec l’utilisation d’axios

FougereBle

Dans le cas d’une utilisation avec un rendu SSR : <—(edit: rajout de cette précision)

Tu as un exemple ici, après le reste de la doc explique, notamment ici pour les routers. En faite la documentation utilise principalement agios pour plusieurs raisons :

  • Vuejs c’est pour les vues, la doc ne se complique pas la vie à expliquer le M et le C ;
  • Agios c’est bien quand tu as le M et le C distant (une API par exemple).

Mais dans ton cas, vu que ton application réuni les éléments MVC, je pense qu’agios n’est pas adapté à moins de justifier la séparation distinct entre les modèles & controller et la gestion des vues.

+0 -0

Sinon j’ai build vuejs et je l’ai intégré à nododejs mais je n’arrive pas à mettre mon application en ligne… quand même, ces technos sont ultra dur à maîtriser et utiliser… beaucoup plus que php.

T’as déjà essayé d’installer et de configurer un projet Symfony quand y’a un souci? :D je préfère bien plus ces frameworks. Après oui, faut bien comprendre ce qu’on fait (et l’authentification c’est pas le plus clair en JS, même avec passport… :( )

Je ne comprend toujours pas comment faire. Je viens de créer un projet de test : projet/ pour le backend, project/frontend pour le frontend.

project/app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'frontend')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

project/routes/index.js

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.sendFile('/opt/lampp/htdocs/p/testpress/frontend/index.html')
  //res.render('index', { title: 'Express' });
});

module.exports = router;

project/frontend/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>frontend</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

Quand je fait un npm start, je me retrouve avec une page blanche. Suis-je obligé de faire un npm run build sur le frontend ? Dans ce cas, ça va être pénible pendant le développement si je dois lancer la commande à chaques changements.

@Genroa : Je n’ai pas beaucoup utilisé Symfony et ça fait un petit moment, mais c’était bien plus simple que ça. Là, j’ai l’impression d’être totalement dépassé. Je ne comprend absolument rien, et le fait qu’il existe 13 façon de faire une même chose n’aide clairement pas. D’ailleurs, je n’ai absolument aucune idée de comment mettre un projet NodeJS en ligne. Mais on verra ça plus tard…

+0 -0

Oui, mais du coup comment je fait sans faire un npm build ? J’ai essayé avec et ça marche super bien. Mais si je dois faire npm build à chaque fois que je fait une modification dans mon code, le développement va être long et chiant.

Déjà que c’est pas cool de devoir faire un npm run dev tout le temps et que ça prend des plombs…

Edit : Je comprend toujours pas… avec ce que j’ai fait, je suis quand même obligé d’utiliser Axios, non ? Je veux dire, comment je fait communiquer VueJS avec Express ?

+0 -0

Oui, ça OK, mais je croyais que le but c’était de se séparer d’Axios, que ce module n’était pas obligatoire ?

Mais dans ton cas, vu que ton application réuni les éléments MVC, je pense qu’agios n’est pas adapté à moins de justifier la séparation distinct entre les modèles & controller et la gestion des vues.

+0 -0

Ah, je me disais bien aussi. :D

Bon, je crois que j’en sais assez sur NodeJS pour continuer tranquillement. J’ai même réussi à mettre en ligne mon premier site NodeJS ! Bon ok, comme mon projet ne fonctionnait pas sur l’hébergeur, j’ai décidé d’héberger un projet vierge… mais c’est déjà bien. :D

Par contre, avant de "fermer" ce sujet, j’aimerais une confirmation sur quelque chose (j’en ai besoin pour continuer de la meilleure façon) :

  • NodeJS est un serveur Web bas niveau en JavaScript qui ne propose pas grand chose
  • Il faut donc installer un framework backend par dessus, comme Express, pour ajouter le système de routing (et quoi d’autres ?)
  • Il faut aussi ajouter un module de session comme Express-session
  • Il faut ajouter un module d’authentification comme JWT ou Passport
  • Il faut ajouter en plus un module de moteur de template (j’ai pas de nom encore)
  • Et un module de basse de données, comme Sequelize
  • Ca, c’est le minimum
  • Ensuite, il existe des framework frontend comme Angular, VueJS ou React
  • Le moteur de template n’est donc plus necessaire dans le backend
  • Ces framework font des appels d’URL sur le Backend avec Axios par exemple pour récupérer des données
  • Ils transforment ces données JSON en HTML

Derniere chose :

  • Lorsque le visiteur va sur le site, il télécharge notre frontend (c’est que du JS)
  • Lorsque il reviens, le JS n’est pas téléchargé de nouveau car dans le cache
  • Du coup, le site est légé et rapide à charger car les données sont sous format JSON

J’ai juste ?

Et l’ultime question : Quand est-il du référencement avec VueJS, étant donné que c’est en SPA et qu’il me semble que c’est mauvais pour le référencement ?

+0 -0

Pour le référencement déjà : oui, une SPA telle quelle c’est assez mauvais. Les crawlers semblent complètement perdus. Pour cela, on utilise le SSR. (server-side rendering). En très gros, lors de l’arrivée sur le site, le serveur génère la page "comme avec PHP" et retourne à la fois la page déjà générée et le packaging pour que pour toute la suite de la navigation, l’app front se comporte comme une SPA. Ca veut dire que tu as d’un coté la vitesse des SPA, et la possibilité d’avoir un bon référencement vu que le crawler (qui va juste naviguer d’url en url comme s’il arrivait sur le site à chaque fois) ne sera pas perdu. Car qui dit page pré-générée dit métadonnées accessibles aux robots.

Pour le reste:

  • nodeJS n’est pas un serveur web. C’est un environnement d’exécution du JS, qui fournit des API supplémentaires pour, par exemple, accéder au disque dur. Ca en fait l’environnement par excellence pour écrire un serveur web en JS. Il permet d’écrire du code qui tourne dans des conditions "standard" comme un programme exécuté sur un OS, et pas dans l’environnement "sandbox" très verrouillé des navigateurs. Ca ouvre pas mal de possibilités, dont l’écriture de serveurs webs, d’applis de bureau, etc.
  • express est la librairie qui est le "serveur web". Comme la majorité des lib/framework JS, comme personne ne fait les mêmes choses ou ne veut installer 100% d’un outil s’il en utilisera seulement 50% (+50% venant d’ailleurs), elles sont souvent séparées en plein de packages qui possèdent souvent des concurrents interchangeables (plus ou moins aisément). Certains packages ne sont par exemple que des connecteurs pour faciliter la mise en place du patchwork "sur mesure" recherché par l’équipe de dev, chaque package ayant ses spécificités pour faire une tâche donnée.
  • Express n’est pas obligatoire. Lorsque tu développes avec Vue par exemple (avec un projet généré par la console ou Vue UI), tu n’écris pas une ligne d’Express et tu n’importes Express nul part. Express est sympathique pour un serveur web simple ou écrire à la main ses petites routes et fonctions contrôleur qui retournent des données. Bien souvent, le framework utilisé simplifie les choses et expose une API pour ça et se charge du reste (les cas fréquents). On peut le voir pour écrire une API de service, mais pour servir les fichiers de l’appli, ça non. C’est fait automatiquement.
  • le moteur de template n’est plus forcément nécessaire coté backend (en cas de SSR, il le faut bien entendu). La spécificité, c’est surtout que pour les frameworks front JS, il est obligatoirement aussi coté front (sinon ça perd tout son intérêt). De même, le routing des vues est généralement coté client.
  • Pour la récupération de données (la seule chose qu’on ne peut pas envoyer coté client, logiquement), Axios, ou tout autre moyen d’appeler un webservice en fait. Pour un REST l’API standard fetch, ou Axios, ou autre, mais on pourrait très bien le faire via des websockets (et là on n’identifie plus une ressource par une route mais par une fonction à appeler coté serveur en lui passant des paramètres).
  • Les données peuvent être retournées de n’importe quelle manière. Ca n’a rien à voir avec le JS, c’est du HTTP classique : le retour pourrait être du JSON, du HTML, du XML, une image, un PDF, on s’en fout. La requête retourne un résultat, le framework l’utilise. :) (le JSON par rapport au HTML vient du fait que le serveur ne se charge plus de générer d’éléments de la vue, il ne sait même pas comment faire en général, donc on laisse le V à la charge du client. Donc juste retourner les données dans un format utilisable suffit)

Pour l’idée du gain de la SPA, c’est ça. Il y a des subtilités, en cas d’usage d’un worker on peut même installer l’appli en hors ligne (sur mobile) et travailler en déconnecté, mais oui le gain principal est là. On "installe" le code nécessaire pour faire tourner une véritable appli écrite en JS, en cache, et le serveur ne sert plus qu’à fournir l’appli pour les nouveaux arrivants, et les données pour les applis qui tournent et les demandent. La manière de penser les choses n’a plus rien à voir avec le classique "page web -> lien -> demande d’une page web à telle url -> PHP génère -> retour nouvelle page web". Ce n’est même pas comparable.

+1 -0

NodeJS est un serveur Web bas niveau en JavaScript qui ne propose pas grand chose

NodeJS n’est pas forcement que pour un serveur HTTP, il propose beaucoup de chose mais pour gagner du temps, il demande de passer par un module

Il faut donc installer un framework backend par dessus, comme Express, pour ajouter le système de routing (et quoi d’autres ?)

Oui pour du rooting améliorer, il faut un module

Il faut ajouter en plus un module de moteur de template (j’ai pas de nom encore)

Non pas si tu as vue.js, tu as une liste ici des plugins compatible à express (via consolidate.js).

Et un module de basse de données, comme Sequelize

C’est à toi de voir, un ORM (Sequelize) est une question de choix/goût

@EtienneR : Je ne savais pas pour body-parser. En fait, j’ai suivis le premier tuto trouvé sur le net pour faire un CRUD avec NodeJS et VueJS, et il fallait installer body-parser.

Mais de toute façon, j’ai jamais bien compris ce qu’était body-parser et à quoi il sert. Il me semble que c’est pour pouvoir récupérer des données de type POST ?

FougereBle

Oui, c’est pour récupérer les données fournies par l’utilisateur dans le body de la requète.

Les middlewares express.json() et express.urlencoded() ont été implémenté (à partir de body-parser) dans la version 4.16.0 de Express. C’est pour cela qu’il y a encore des traces de la librairie body-parser dans les tutoriels (aussi bien anciens que récents…).

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte