Methodes cles
Signatures et logique des methodes principales de Place API - handlers, services et methodes de domaine
Methodes cles
Handlers de commandes
LoginCommandHandler.Handle
Fichier : Features/Auth/Login/V1/Login.csSignature :
public async Task<Result<AuthTokensResponse>> Handle(
LoginCommand request, CancellationToken cancellationToken)
Logique :
- Extraire les informations de l'appareil via
IDeviceInfoProvider - Normaliser l'email via le value object
Email - Rechercher l'utilisateur par email dans
UserManager - Verifier le mot de passe via
SignInManager.CheckPasswordSignInAsync(avec lockout) - Verifier que le compte est actif (
IsActive) et que l'email est confirme - Si 2FA active : creer un challenge via
ITwoFactorChallengeServiceet retournerTwoFactorRequiredError - Verifier l'expiration du mot de passe via
IPasswordExpiryService - Construire la reponse tokens via
IAuthTokenResponseBuilder.BuildAsync - Enregistrer le login (
User.RecordLogin()) et dispatcher les evenements de domaine - Logger le succes via
ISecurityAuditet enregistrer les metriques
RegisterCommandHandler.Handle
Fichier : Features/Auth/Register/V1/Register.csSignature :
public async Task<Result<AuthTokensResponse>> Handle(
RegisterCommand request, CancellationToken cancellationToken)
Logique :
- Normaliser l'email
- Creer l'utilisateur via
IUserRegistrationService.CreateUserWithPasswordAsync - Gerer les cas d'erreur avec pattern matching sur
UserCreationResult:DuplicateEmail: retournerConflictErrorWeakPassword: retournerBadRequestErrorCreationFailed: retournerBadRequestErrorSuccess: construire la reponse tokens
- L'evenement
SendConfirmationEmailOnUserRegisteredest publie via notification MediatR
RefreshTokenCommandHandler.Handle
Fichier : Features/Auth/RefreshToken/V1/RefreshToken.csSignature :
public async Task<Result<AuthTokensResponse>> Handle(
RefreshTokenCommand request, CancellationToken cancellationToken)
Logique detaillee :
- Extraire les informations de l'appareil
- Hasher le refresh token recu avec HMAC-SHA256 + pepper
- Rechercher la session par hash du refresh token
- Si session non trouvee :
- Rechercher par
PreviousRefreshTokenHash(token precedent) - Si trouve et dans la periode de grace (30 secondes) : rejeter silencieusement
- Si trouve hors grace : replay detecte -> revoquer toutes les sessions de l'utilisateur
- Si non trouve : token invalide
- Rechercher par
- Si session revoquee :
- Si revoquee pour
TokenRotation: replay detecte -> revoquer toutes les sessions - Sinon : retourner
SessionRevokedError
- Si revoquee pour
- Verifier l'expiration de la session
- Verifier le binding de session (IP et DeviceId) si
EnforceSessionBindingest active - Verifier que l'utilisateur est toujours actif
- Construire les nouveaux claims avec
ClaimsBuilder.BuildClaims - Generer un nouveau access token et un nouveau refresh token
- Rotation du token :
SessionWriter.RotateTokenAsync(l'ancien hash devientPreviousRefreshTokenHash) - Construire et retourner la reponse
LogoutCommandHandler
Revoque la session courante en utilisant l'identifiant de session extrait du token JWT.
SocialLoginCommandHandler
- Valide le token du provider social (Google, Facebook, Apple)
- Recherche un
UserLoginexistant pour ce provider - Si l'utilisateur existe : connexion directe
- Sinon : creation d'un nouveau compte via
CreateUserWithExternalProviderAsync - Remplit le profil social (
FillSocialProfile)
Methodes de domaine (entites)
User.Register (factory)
public static User Register(
string username, string normalizedEmail,
string? firstName, string? lastName, string? imageUrl)
Cree une nouvelle instance de User avec IsActive = true et EmailConfirmed = false.
User.RecordLogin
public void RecordLogin()
Met a jour LastLoginAt et ajoute un UserLoggedInEvent aux evenements de domaine.
User.Activate / User.Deactivate
public void Activate(string? reason)
public void Deactivate(string? reason)
Change l'etat IsActive et ajoute un evenement de domaine (UserActivatedEvent / UserDeactivatedEvent). Operateurs idempotents : si l'etat est deja le meme, rien ne se passe.
UserSession.Create (factory)
internal static UserSession Create(NewSessionData data, DateTime createdAt)
Cree une session a partir des donnees de session (utilisateur, token, appareil) et emet un SessionCreatedEvent.
UserSession.Revoke
internal bool Revoke(RevocationReason? reason, DateTime revokedAt)
Marque la session comme revoquee. Retourne false si deja revoquee (idempotent). Emet un SessionRevokedEvent.
UserSession.UpdateActivity
internal void UpdateActivity(HashedToken newRefreshTokenHash, DateTime now)
Met a jour le hash du refresh token et deplace l'ancien vers PreviousRefreshTokenHash. Met a jour LastActivityAt.
HashedToken.FromRaw
public static HashedToken FromRaw(string rawToken, byte[] pepper)
Hash un token brut avec HMAC-SHA256 et un pepper. Produit un Hash complet et un Fingerprint (8 premiers caracteres du hash).
OtpRecord.IncrementAttempt / MarkUsed
public void IncrementAttempt()
public void MarkUsed()
TwoFactorChallenge.IncrementAttempt / MarkConsumed
public void IncrementAttempt()
public void MarkConsumed()
Methodes de services
AuditLogWriter.WriteAsync
public async Task WriteAsync(AuditEventV1 auditEvent, CancellationToken cancellationToken)
- Convertit
AuditEventV1en entiteAuditLog(mapping des enums en strings snake_case) - Persiste en base via
AuditContext - Enregistre les metriques de performance
- Broadcast via SignalR vers le groupe
audit-admins - En cas d'echec du broadcast, logue un warning sans bloquer
ClaimsBuilder.BuildClaims
public static IReadOnlyList<Claim> BuildClaims(User user, IReadOnlyList<string> roles, SessionId sessionId)
Construit la liste des claims JWT pour un utilisateur donne, incluant les roles et l'identifiant de session.
MessagingPersistenceBehavior.Handle
public async Task<TResponse> Handle(
TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
- Extraire le message de la commande (
IMessagingCommand.Message) - Creer un
SentMessageavec le statutPendinget le persister - Executer le handler reel (envoi SMTP, SNS, push)
- En cas de succes : mettre a jour le statut en
Sent - En cas d'echec : mettre a jour le statut en
Failedavec le message d'erreur - Dans le
finally: persister le resultat final
SendEmailCommandHandler.Handle
public async Task<Unit> Handle(SendEmailCommand request, CancellationToken cancellationToken)
- Rendre le template MJML via
ITemplateRenderer.Render() - Envoyer l'email via
IEmailSender.SendAsync()