Identity — Authentification JWT

Le système d’authentification étend SimpleJWT pour injecter les claims tenant dans les tokens JWT.

Module : src.module.identity.infrastructure.authentication

CustomTokenObtainPairSerializer

class src.module.identity.infrastructure.authentication.CustomTokenObtainPairSerializer(TokenObtainPairSerializer)

Sérialiseur JWT qui injecte les claims tenant dans le token d’accès.

Claims ajoutés :

  • tenant_id : UUID du tenant courant

  • roles : Liste des rôles de la membership

  • email : Email de l’utilisateur

classmethod get_token(cls, user) Token

Génère un token avec les claims tenant injectés.

Configuration dans settings.py :

SIMPLE_JWT = {
    'TOKEN_OBTAIN_SERIALIZER': 'src.module.identity.infrastructure.authentication.CustomTokenObtainPairSerializer',
}

Exemple de payload JWT décodé :

{
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "admin@acme.com",
    "tenant_id": "660e8400-e29b-41d4-a716-446655440001",
    "roles": ["admin", "billing"],
    "exp": 1711200000,
    "iat": 1711196400
}

CustomJWTAuthentication

class src.module.identity.infrastructure.authentication.CustomJWTAuthentication(JWTAuthentication)

Backend d’authentification JWT qui extrait le tenant_id depuis le token pour que le TenantMiddleware puisse l’utiliser.

Étend JWTAuthentication de SimpleJWT.

Endpoints d’authentification

Module : src.module.identity.presentation.views

class src.module.identity.infrastructure.authentication.RegisterView(CreateAPIView)

POST /api/v1/auth/register/

Crée un nouvel utilisateur.

Body:

{"email": "...", "password": "...", "first_name": "...", "last_name": "..."}

Response 201:

{"id": "...", "email": "..."}

class src.module.identity.infrastructure.authentication.LoginView(TokenObtainPairView)

POST /api/v1/auth/login/

Authentifie un utilisateur et retourne les tokens JWT.

Body:

{"email": "...", "password": "..."}

Response 200:

{"access": "eyJ...", "refresh": "eyJ..."}

Si OTP_REQUIRED_FOR_LOGIN est activé, retourne un token temporaire qui nécessite une vérification OTP avant utilisation.

class src.module.identity.infrastructure.authentication.SwitchTenantView(APIView)

POST /api/v1/auth/switch-tenant/

Génère un nouveau token JWT pour un autre tenant.

Body:

{"tenant_id": "..."}

Response 200:

{"access": "eyJ...", "refresh": "eyJ..."}

Vérifie que l’utilisateur a une membership active dans le tenant cible.

Flux d’authentification

Client                          Serveur
  │                                │
  ├── POST /auth/login/ ──────────►│
  │   {email, password}            │
  │                                ├── Vérifie les credentials
  │                                ├── Injecte tenant_id dans JWT
  │                                │
  │◄── {access, refresh} ──────────┤
  │                                │
  ├── GET /api/v1/products/ ──────►│
  │   Authorization: Bearer eyJ... │
  │                                ├── CustomJWTAuthentication
  │                                │   extrait user + tenant_id
  │                                ├── TenantMiddleware
  │                                │   active le backend d'isolation
  │                                ├── ABACPermission
  │                                │   évalue les politiques
  │                                │
  │◄── [data scopée au tenant] ────┤