Pourquoi Authentification dans Nuxt ?
L'authentification est un élément crucial en développement web, permettant aux utilisateurs de s'identifier et d'avoir accès à des fonctionnalités restreintes. Dans le contexte professionnel, une authentification bien structurée améliore la sécurité, la productivité et l’expérience utilisateur. Un cas concret est une application e-commerce où les utilisateurs doivent être identifiés pour effectuer des achats ou accéder à leur historique de commande.
Prerequis
- Connaissance avancée de Nuxt.js
- Expérience avec Vue.js et JavaScript
- Familiarité avec le concept de state management (Vuex)
- Compréhension des concepts de composants, routes et middleware
Outils à installer :
- Node.js v14 ou supérieur
- npm v6 ou supérieur
- Git pour la gestion du code source
Concepts fondamentaux
1. Middleware d'authentification
Le middleware est un outil puissant en Nuxt qui permet de gérer des actions avant et après le rendu des pages. Pour l'authentification, nous utilisons des middlewares pour vérifier si un utilisateur est connecté.
// middleware/auth.js
export default function ({ store, redirect }) {
if (!store.state.authenticated) {
return redirect('/login')
}
}
2. Store Vuex pour la gestion de l'état d'authentification
Vuex est un state management pour Vue.js qui permet une gestion globale et prévisible des états. Nous utiliserons Vuex pour stocker les informations de l'utilisateur connecté.
// store/auth.js
export const state = () => ({
authenticated: false,
user: null
})
export const mutations = {
setAuthenticated(state, status) {
state.authenticated = status
},
setUser(state, user) {
state.user = user
}
}
3. Composant de formulaire d'authentification
Pour permettre aux utilisateurs de s'inscrire et de se connecter, nous créons des composants de formulaires.
// components/LoginForm.vue
<template>
<form @submit.prevent="login">
<input type="text" v-model="email" placeholder="Email" required />
<input type="password" v-model="password" placeholder="Password" required />
<button type="submit">Login</button>
</form>
</template>
<script>
export default {
data() {
return {
email: '',
password: ''
}
},
methods: {
async login() {
try {
const response = await this.$axios.post('/api/login', {
email: this.email,
password: this.password
})
this.$store.commit('auth/setAuthenticated', true)
this.$store.commit('auth/setUser', response.data.user)
this.$router.push('/')
} catch (error) {
console.error(error)
}
}
}
}
</script>
Mise en pratique : projet fil rouge
Nous allons créer un gestionnaire de tâches simple. Ce projet comprendra des fonctionnalités d'inscription, de connexion et de création/modification/suppression de tâches.
Étape 1 : Création du projet Nuxt.js
npx create-nuxt-app task-manager
cd task-manager
npm run dev
Étape 2 : Configuration des middlewares
Créer un middleware auth.js pour protéger les routes nécessitant une authentification.
// middleware/auth.js
export default function ({ store, redirect }) {
if (!store.state.authenticated) {
return redirect('/login')
}
}
Étape 3 : Configuration du store Vuex
Créer un fichier auth.js dans le dossier store.
// store/auth.js
export const state = () => ({
authenticated: false,
user: null
})
export const mutations = {
setAuthenticated(state, status) {
state.authenticated = status
},
setUser(state, user) {
state.user = user
}
}
Étape 4 : Création des composants
Créer un composant LoginForm.vue.
// components/LoginForm.vue
<template>
<form @submit.prevent="login">
<input type="text" v-model="email" placeholder="Email" required />
<input type="password" v-model="password" placeholder="Password" required />
<button type="submit">Login</button>
</form>
</template>
<script>
export default {
data() {
return {
email: '',
password: ''
}
},
methods: {
async login() {
try {
const response = await this.$axios.post('/api/login', {
email: this.email,
password: this.password
})
this.$store.commit('auth/setAuthenticated', true)
this.$store.commit('auth/setUser', response.data.user)
this.$router.push('/')
} catch (error) {
console.error(error)
}
}
}
}
</script>
Créer un composant TaskForm.vue.
// components/TaskForm.vue
<template>
<form @submit.prevent="saveTask">
<input type="text" v-model="title" placeholder="Title" required />
<textarea v-model="description"></textarea>
<button type="submit">Save Task</button>
</form>
</template>
<script>
export default {
data() {
return {
title: '',
description: ''
}
},
methods: {
async saveTask() {
try {
const response = await this.$axios.post('/api/tasks', {
title: this.title,
description: this.description
})
this.title = ''
this.description = ''
} catch (error) {
console.error(error)
}
}
}
}
</script>
Étape 5 : Création des routes
Créer une route protégée tasks.vue.
// pages/tasks.vue
<template>
<div>
<h1>Tasks</h1>
<TaskForm />
<ul>
<li v-for="task in tasks" :key="task.id">
task.title - task.description
</li>
</ul>
</div>
</template>
<script>
export default {
middleware: 'auth',
data() {
return {
tasks: []
}
},
async fetch() {
try {
this.tasks = await this.$axios.get('/api/tasks')
} catch (error) {
console.error(error)
}
}
}
</script>
Étape 6 : Création des API routes
Créer une route pour l'authentification et les tâches.
// server/api/auth.js
export default function ({ $axios, params }) {
if (params.action === 'login') {
return $axios.$post('/api/login', { email: params.email, password: params.password })
}
}
nuxt
// server/api/tasks.js
export default function ({ $axios, params }) {
if (params.action === 'list') {
return $axios.$get('/api/tasks')
} else if (params.action === 'create') {
return $axios.$post('/api/tasks', { title: params.title, description: params.description })
}
}
Erreurs frequentes et debugging
1. Middleware non exécuté
Code incorrect :
// middleware/auth.js
export default function ({ store, redirect }) {
if (store.state.authenticated) {
return redirect('/dashboard')
}
}
Code correct :
// middleware/auth.js
export default function ({ store, redirect }) {
if (!store.state.authenticated) {
return redirect('/login')
}
}
2. Erreur dans la requête API
Code incorrect :
this.$axios.get('/api/tasks').then(response => {
this.tasks = response.data
}).catch(error => {
console.error(error)
})
Code correct :
try {
const response = await this.$axios.get('/api/tasks')
this.tasks = response.data
} catch (error) {
console.error(error)
}
3. Problème avec le state Vuex
Code incorrect :
// store/auth.js
export const mutations = {
setAuthenticated(state, status) {
state.authenticated = status
},
setUser(state, user) {
state.user = user
}
}
Code correct :
// store/auth.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: () => ({
authenticated: false,
user: null
}),
mutations: {
setAuthenticated(state, status) {
state.authenticated = status
},
setUser(state, user) {
state.user = user
}
}
})
Pour aller plus loin
- Intégration avec OAuth : Ajouter une authentification via des services tiers comme Google, Facebook ou GitHub.
- Gestion de l'état utilisateur avec Pinia : Utiliser Pinia, le nouveau state management de Vue.js 3, pour gérer les états de l'application.
- Tests unitaires et d'intégration : Ajouter des tests pour s'assurer que votre application fonctionne correctement.
Défi pratique :
- Créez un mini-projet de gestion de projet en utilisant Nuxt.js, Vue.js et Vuex. Implémentez une authentification avec middleware et routes protégées.