Authentification SSO — A1Connect ↔ Inspire V2
Vue d'ensemble
L'authentification repose sur deux JWT distincts qui ne doivent pas être confondus :
JWT A1Connect (sessionJwt) |
JWT Inspire (loginToken) |
|
|---|---|---|
| Signé par | A1Connect (clé privée A1C) | Inspire V2 (sa propre clé privée) |
| Algorithme | RS256 | RS256 |
| Durée | courte / session | 30 jours |
| Usage | handshake SSO uniquement | toutes les requêtes API Inspire |
| Transmis via | Authorization: Bearer (A1C API) |
Authorization: Bearer (Inspire API) |
Il n'y a pas de cookie. Les deux applications utilisent exclusivement des Bearer tokens.
Flux SSO complet (navigateur — production)
1. Frontend Inspire
└─ GET /auth-jwt/sso-jwt
→ Inspire génère un JWT signé (payload: redirect_uri, profile_token)
→ Renvoie ce JWT au frontend
2. Frontend
└─ Redirige le navigateur vers A1Connect avec ce JWT en paramètre
3. Utilisateur s'authentifie sur A1Connect (login/mdp)
4. A1Connect
└─ POST /auth-jwt/sso-redirect (sur l'API Inspire)
body: { profile_jwt: "<jwt signé par A1C>" }
→ Inspire vérifie la signature avec la clé publique A1C (SSO_PUBLIC_KEY)
→ Find or create user en base (par ssoId puis par email)
→ Génère son propre JWT Inspire (30j, payload: { id, username })
→ HTTP 302 → FRONTEND_URL/auth/callback?loginToken=<jwt_inspire>&isSignUp=...
5. Frontend
└─ Stocke loginToken
└─ Envoie Authorization: Bearer <loginToken> sur toutes les requêtes Inspire
Tester avec Bruno
Option A — Login direct (recommandé en dev)
Inspire expose un endpoint username/password pour le développement :
POST http://localhost:3236/auth-jwt/login
body: { "username": "...", "password": "..." }
→ 200 { "token": "<jwt_inspire>" }
→ Utiliser la request Auth > Login dans la collection Bruno d'Inspire.
Le token est auto-sauvegardé dans {{token}}.
Créer un utilisateur de dev : ne pas insérer en base directement — le mot de passe doit être bcrypté. Passer par l'endpoint register :
POST http://localhost:3236/auth-jwt/register
body: { "username": "dev@example.com", "password": "Test1234!" }
Les users créés via register ont activated = false par défaut. Pour contourner sans attendre l'email :
UPDATE "user-jwt" SET activated = true WHERE username = 'dev@example.com';
Note sur le nom de la table
user-jwt: c'est la table des utilisateurs natifs d'Inspire (ceux qui s'authentifient en local par username/password), pas une table de tokens JWT. Le nom vient du moduleauth-jwt. Les users SSO (qui passent par A1Connect) sont dans la tableusers.
Option B — Simuler le flux SSO complet
Utile pour tester le comportement de sso-redirect (find-or-create, isSignUp, etc.).
Étape 1 — S'authentifier sur A1Connect (auth/01-login) → sauvegarde {{sessionJwt}}
Étape 2 — Générer un profile_jwt (auth/04-profile-jwt) → sauvegarde {{profileJwt}}
Le body doit contenir "audience": "inspire".
Étape 3 — Appeler le sso-redirect d'Inspire :
POST http://localhost:3236/auth-jwt/sso-redirect
body: { "profile_jwt": "{{profileJwt}}" }
→ Inspire retourne un HTTP 302 vers FRONTEND_URL/auth/callback?loginToken=<jwt>
→ Extraire le loginToken de l'URL de redirection et l'utiliser comme Bearer.
Variables d'environnement concernées
A1Connect (Bruno)
sessionJwt— JWT A1C, obtenu viaauth/01-loginprofileJwt— JWT de profil A1C, obtenu viaauth/04-profile-jwt
Inspire V2 (Bruno, collection séparée)
token— JWT Inspire (30j), obtenu viaauth/loginou extrait du callback SSO
Configuration serveur
| Variable | A1Connect | Inspire V2 |
|---|---|---|
JWT_PRIVATE_KEY |
Signe les profile_jwt |
Signe les loginToken |
JWT_PUBLIC_KEY |
— | Valide ses propres loginToken |
SSO_PUBLIC_KEY |
— | Valide les profile_jwt reçus d'A1C |
SSO_ISSUER / SSO_AUDIENCE |
— | Utilisés lors de la création du JWT SSO |