Authentification
Cette page décrit comment utiliser l'API d'authentification de GestSIS pour créer et gérer les tokens d'accès et de rafraîchissement.
Vue d'ensemble
L'API d'authentification GestSIS utilise un système de tokens JWT (JSON Web Tokens) pour sécuriser les accès. Deux types de tokens sont utilisés :
- Access Token : Token de courte durée (8 heures) utilisé pour authentifier les requêtes API
- Refresh Token : Token de longue durée (30 jours) utilisé pour renouveler l'access token
Base URL
L'API d'authentification est accessible via :
http://auth.gestsis.ch/api/v1
En production, l'URL sera différente selon votre configuration.
1. Connexion (Login)
Endpoint
POST /api/v1/login
Description
Permet à un utilisateur de se connecter et d'obtenir un access token et un refresh token.
Corps de la requête
{
"email": "utilisateur@example.com",
"password": "motdepasse"
}
Réponse en cas de succès (200 OK)
{
"message": "Successful login",
"accessToken": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refreshToken": "a1b2c3d4e5f6g7h8",
"user": {
"id": 1,
"name": "Jean Dupont",
"email": "utilisateur@example.com",
"email_verified_at": "2025-01-01T10:00:00.000000Z",
"created_at": "2025-01-01T10:00:00.000000Z",
"updated_at": "2025-01-01T10:00:00.000000Z"
}
}
Réponse en cas d'erreur (401 Unauthorized)
Ou en cas de validation échouée :
Exemple avec cURL
curl -X POST http://auth.gestsis.ch/api/v1/login \
-H "Content-Type: application/json" \
-d '{
"email": "utilisateur@example.com",
"password": "motdepasse"
}'
Exemple avec JavaScript (fetch)
const response = await fetch('http://auth.gestsis.ch/api/v1/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'utilisateur@example.com',
password: 'motdepasse'
})
});
const data = await response.json();
if (response.ok) {
console.log('Access Token:', data.accessToken);
console.log('Refresh Token:', data.refreshToken);
// Stocker les tokens (par exemple dans localStorage)
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
} else {
console.error('Erreur de connexion:', data.error);
}
2. Rafraîchir le Token (Refresh Token)
Endpoint
POST /api/v1/refresh-token
Description
Permet de renouveler l'access token en utilisant le refresh token. Le refresh token est à usage unique : après utilisation, il est détruit et un nouveau refresh token est généré.
Corps de la requête
{
"token": "a1b2c3d4e5f6g7h8"
}
Réponse en cas de succès (200 OK)
{
"message": "Successful login",
"accessToken": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refreshToken": "x9y8z7w6v5u4t3s2",
"user": {
"id": 1,
"name": "Jean Dupont",
"email": "utilisateur@example.com",
"email_verified_at": "2025-01-01T10:00:00.000000Z",
"created_at": "2025-01-01T10:00:00.000000Z",
"updated_at": "2025-01-01T10:00:00.000000Z"
}
}
Réponse en cas d'erreur (401 Unauthorized)
Ou en cas de validation échouée :
Exemple avec cURL
curl -X POST http://auth.gestsis.ch/api/v1/refresh-token \
-H "Content-Type: application/json" \
-d '{
"token": "a1b2c3d4e5f6g7h8"
}'
Exemple avec JavaScript (fetch)
const refreshToken = localStorage.getItem('refreshToken');
const response = await fetch('http://auth.gestsis.ch/api/v1/refresh-token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
token: refreshToken
})
});
const data = await response.json();
if (response.ok) {
// Mettre à jour les tokens stockés
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
console.log('Tokens renouvelés avec succès');
} else {
console.error('Erreur de rafraîchissement:', data.error);
// Si le refresh token a expiré, rediriger vers la page de connexion
if (data.error === 'Refresh token expired') {
window.location.href = '/login';
}
}
Utilisation des Tokens
Structure de l'Access Token
L'access token est un JWT (JSON Web Token) signé avec RSA-256 qui contient les informations suivantes :
Structure complète
{
"iss": "GestSIS_Auth",
"aud": "GestSIS_API",
"iat": 1702290000,
"nbf": 1702289990,
"exp": 1702318800,
"data": {
"id": 1,
"admin": false,
"validated": true,
"pseudo": "Jean Dupont",
"email": "jean.dupont@example.com",
"permissions": {
"test": [
"intervention.lecture",
"intervention.modification",
"sapeur.lecture"
],
"hs": [
"intervention.lecture"
]
},
"mobiles": [
"test",
"hs"
],
"sapeurs": {
"test": 42,
"hs": 108
}
}
}
Description des champs
Headers JWT standard :
- iss (Issuer) :
GestSIS_Auth- Émetteur du token - aud (Audience) :
GestSIS_API- Destinataire du token - iat (Issued At) : Timestamp UNIX de la création du token
- nbf (Not Before) : Timestamp UNIX à partir duquel le token est valide (10 secondes avant iat)
- exp (Expiration) : Timestamp UNIX d'expiration (8 heures après iat)
Données utilisateur (data) :
- id : Identifiant unique de l'utilisateur dans GestSIS_Auth
- admin : Booléen indiquant si l'utilisateur est administrateur (a tous les droits sur tous les SIS)
- validated : Booléen indiquant si l'email de l'utilisateur a été vérifié
- pseudo : Nom d'affichage de l'utilisateur
- email : Adresse email de l'utilisateur
Données multi-SIS :
- permissions : Objet où chaque clé est l'
api_keyd'un SIS, contenant un tableau des permissions pour ce SIS- Exemple :
{"test": ["intervention.lecture", "sapeur.modification"]} - Si l'utilisateur est admin, toutes les clés SIS contiennent
["admin"]
- Exemple :
- mobiles : Tableau simple contenant les
api_keydes SIS pour lesquels l'utilisateur peut recevoir des alertes mobiles- Exemple :
["test", "hs"]
- Exemple :
- sapeurs : Objet où chaque clé est l'
api_keyd'un SIS, contenant l'ID du sapeur associé à l'utilisateur dans ce SIS- Exemple :
{"test": 42, "hs": 108}
- Exemple :
Architecture multi-tenant
Important : Les permissions, mobiles et sapeurs sont organisés par SIS. Cela permet à un utilisateur :
- D'avoir des permissions différentes selon le SIS
- D'être sapeur dans plusieurs SIS avec des IDs différents
- De recevoir des alertes mobiles uniquement pour certains SIS
Exemple : Un utilisateur peut être chef d'intervention dans le SDIS Jura mais simple sapeur dans le SDIS Neuchâtel.
Utiliser l'Access Token dans les requêtes API
Pour authentifier une requête API, incluez l'access token dans le header Authorization :
Authorization: Bearer {accessToken}
Exemple complet d'utilisation
// 1. Connexion
const loginResponse = await fetch('http://auth.gestsis.ch/api/v1/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'utilisateur@example.com',
password: 'motdepasse'
})
});
const loginData = await loginResponse.json();
localStorage.setItem('accessToken', loginData.accessToken);
localStorage.setItem('refreshToken', loginData.refreshToken);
// 2. Utiliser l'access token pour une requête protégée
const apiResponse = await fetch('http://apis.gestsis.ch/api/v1/protected-resource', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('accessToken')}`
}
});
// 3. Si le token a expiré (erreur 401), le rafraîchir
if (apiResponse.status === 401) {
const refreshResponse = await fetch('http://auth.gestsis.ch/api/v1/refresh-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: localStorage.getItem('refreshToken')
})
});
const refreshData = await refreshResponse.json();
localStorage.setItem('accessToken', refreshData.accessToken);
localStorage.setItem('refreshToken', refreshData.refreshToken);
// Réessayer la requête avec le nouveau token
const retryResponse = await fetch('http://apis.gestsis.ch/api/v1/protected-resource', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('accessToken')}`
}
});
}
Bonnes Pratiques
Sécurité
- Ne jamais exposer les tokens : Ne jamais afficher les tokens dans les logs ou les messages d'erreur
- Stockage sécurisé : Utiliser des mécanismes sécurisés pour stocker les tokens (httpOnly cookies pour le web)
- HTTPS uniquement : Toujours utiliser HTTPS en production pour éviter l'interception des tokens
- Refresh token à usage unique : Le système utilise des refresh tokens à usage unique pour prévenir le vol de tokens
Gestion des Tokens
- Renouvellement automatique : Implémenter un mécanisme de renouvellement automatique avant l'expiration
- Gestion des erreurs : Rediriger vers la page de connexion si le refresh token a expiré
- Déconnexion : Supprimer les tokens stockés lors de la déconnexion
// Fonction utilitaire pour gérer le renouvellement automatique
async function fetchWithAuth(url, options = {}) {
const token = localStorage.getItem('accessToken');
const response = await fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${token}`
}
});
// Si le token a expiré, le rafraîchir et réessayer
if (response.status === 401) {
const refreshToken = localStorage.getItem('refreshToken');
const refreshResponse = await fetch('http://auth.gestsis.ch/api/v1/refresh-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: refreshToken })
});
if (refreshResponse.ok) {
const data = await refreshResponse.json();
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
// Réessayer la requête originale
return fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${data.accessToken}`
}
});
} else {
// Refresh token expiré, rediriger vers login
window.location.href = '/login';
throw new Error('Session expirée');
}
}
return response;
}
Durée de vie des Tokens
- Access Token : 8 heures
- Refresh Token : 30 jours
- Reset Token : 1 heure
- Confirmation Token : 30 jours
Autres Endpoints d'Authentification
Inscription
POST /api/v1/register
Permet de créer un nouveau compte utilisateur.
Confirmation d'Email
POST /api/v1/confirmer-email
Permet de confirmer l'adresse email d'un nouvel utilisateur.
Mot de Passe Oublié
POST /api/v1/forgotten-password
Demande un lien de réinitialisation de mot de passe.
Réinitialiser le Mot de Passe
POST /api/v1/reset-password
Réinitialise le mot de passe avec un token de réinitialisation.
Changer le Mot de Passe
POST /api/v1/change-password
Permet à un utilisateur authentifié de changer son mot de passe.