Pourquoi Authentification dans Astro ?
L'authentification est un élément fondamental pour la sécurité des applications web, permettant aux utilisateurs d'accéder à une partie spécifique de l'application en fonction de leurs droits et de leurs identifiants. Dans le contexte professionnel, il est crucial de comprendre comment gérer l'authentification efficacement, car elle protège les données sensibles et maintient la confidentialité des utilisateurs.
Un cas d'usage concret est une application de gestion de contenu (CMS) où les utilisateurs doivent se connecter pour publier des articles. Sans authentification, n'importe quel utilisateur pourrait modifier les contenus publiés par d'autres, ce qui serait une menace majeure pour la sécurité et l'intégrité du site.
Prerequis
- Connaissance de base d'Astro
- Familiarité avec JavaScript et TypeScript
- Compétence en gestion des paquets npm
- Connaissance des concepts de state management (comme le context API dans React)
Outils à installer :
- Node.js v14 ou plus récent
- npm v6 ou plus récent
Concepts fondamentaux
1. Authentification vs Autorisation
L'authentification est la vérification que l'utilisateur est qui il prétend être, tandis qu'autorisation détermine ce que l'utilisateur peut faire une fois authentifié.
// Exemple simplifié de login avec fetch et JWT (JSON Web Token)
async function login(username, password) {
const response = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
});
if (response.ok) {
const data = await response.json();
localStorage.setItem('token', data.token);
} else {
throw new Error('Invalid credentials');
}
}
2. Middleware
Le middleware est une fonction qui reçoit les objets request et response, et le callback next en tant que paramètres.
// Exemple de middleware pour vérifier l'authentification avant d'accéder à certaines routes
export function authMiddleware(req, res, next) {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ message: 'Authentication required' });
}
try {
// Vérifiez le token JWT et continuez si valide
next();
} catch (err) {
return res.status(403).json({ message: 'Invalid token' });
}
}
3. State Management
Le state management gère les états de votre application, permettant de partager des données entre les composants.
// Utilisation du context API pour partager le token d'authentification
import { createContext, useContext } from 'react';
export const AuthContext = createContext();
export function useAuth() {
return useContext(AuthContext);
}
Mise en pratique : projet fil rouge
Nous allons créer un mini-projet complet : une application de gestion de tâches où les utilisateurs peuvent se connecter, ajouter et afficher leurs tâches.
Étape 1 : Initialisation du projet
npx create-astro my-todo-app
cd my-todo-app
npm install react react-dom @astrojs/react
Étape 2 : Création des composants
Créer les fichiers suivants :
src/components/Login.astrosrc/components/TodoList.astrosrc/components/AddTodo.astrosrc/pages/index.astro
// src/components/Login.astro
---
import { useState } from 'react';
---
<form onSubmit={async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const username = formData.get('username');
const password = formData.get('password');
try {
await login(username, password);
window.location.href = '/';
} catch (error) {
alert(error.message);
}
}}>
<input type="text" name="username" placeholder="Username" required />
<input type="password" name="password" placeholder="Password" required />
<button type="submit">Login</button>
</form>
astro
// src/components/TodoList.astro
---
import { useAuth } from '../context/AuthContext';
---
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
astro
// src/components/AddTodo.astro
---
import { useState, useContext } from 'react';
import { useAuth } from '../context/AuthContext';
---
<form onSubmit={async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const text = formData.get('text');
try {
await addTodo(text);
window.location.href = '/';
} catch (error) {
alert(error.message);
}
}}>
<input type="text" name="text" placeholder="Add a task" required />
<button type="submit">Add</button>
</form>
astro
// src/pages/index.astro
---
import { useState, useEffect } from 'react';
import { useAuth } from '../context/AuthContext';
const fetchTodos = async () => {
const response = await fetch('/api/todos');
return await response.json();
};
const addTodo = async (text) => {
const response = await fetch('/api/todos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text })
});
if (!response.ok) {
throw new Error('Failed to add todo');
}
};
---
const Home = () => {
const [todos, setTodos] = useState([]);
const auth = useAuth();
useEffect(() => {
if (auth.isAuthenticated) {
fetchTodos().then(setTodos);
}
}, [auth.isAuthenticated]);
return (
<div>
{auth.isAuthenticated ? (
<>
<h1>Todo List</h1>
<AddTodo />
<TodoList todos={todos} />
</>
) : (
<Login />
)}
</div>
);
};
export default Home;
Étape 3 : Configuration du middleware
Créer un fichier middleware.js dans le dossier src.
// src/middleware.js
import { authMiddleware } from './context/AuthContext';
export const onRequest = [authMiddleware];
Erreurs frequentes et debugging
Erreur d'authentification
// code_incorrect try { await login(username, password); } catch (error) { alert(error.message); // "Invalid credentials" }Correction :
// code_correct try { await login(username, password); window.location.href = '/'; } catch (error) { if (error.message === 'Invalid credentials') { alert('Invalid username or password'); } else { alert(error.message); } }Erreur de chargement des tâches
// code_incorrect useEffect(() => { fetchTodos().then(setTodos); }, []);Correction :
// code_correct useEffect(() => { if (auth.isAuthenticated) { fetchTodos().then(setTodos); } }, [auth.isAuthenticated]);Erreur d'ajout de tâche
// code_incorrect const addTodo = async (text) => { await fetch('/api/todos', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text }) }); };Correction :
// code_correct const addTodo = async (text) => { try { await fetch('/api/todos', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text }) }); window.location.href = '/'; } catch (error) { alert(error.message); } };
Pour aller plus loin
Utilisation de OAuth pour une authentification social
Création d'un système de rôles et d'autorisations
Ajout de fonctionnalités de session management
Défi pratique : Ajouter un système de rappels (reminders) aux tâches dans l'application de gestion de tâches.
Note: Ce tutoriel est une introduction approfondie à l'authentification dans Astro, et il peut être adapté pour des projets plus complexes en fonction des besoins spécifiques.