Infrastructure

Composants techniques transversaux - JWT, sessions, OTP, rate limiting, metriques et DbContext

Infrastructure

Configuration JWT

JwtOptions

Defini dans Identity.Infrastructure.Auth.Options.JwtOptions :

OptionDescription
PrivateKeyBase64Cle privee RSA en Base64 pour la signature des tokens
IssuerEmetteur du token (JWT_ISSUER)
AudienceAudience cible (JWT_AUDIENCE)
AccessTokenLifetimeMinutesDuree de vie de l'access token en minutes

Valide au demarrage via JwtOptionsValidator.

TokenService

Implementation de ITokenService dans Identity.Infrastructure.Services.TokenService :

  • Signe les access tokens avec RSA (algorithme RS256)
  • Les refresh tokens sont des chaines aleatoires de 64 octets encodees en Base64
  • Les refresh tokens sont hashes avec HMAC-SHA256 + un pepper secret avant stockage

ClaimsBuilder

Identity.Infrastructure.Services.ClaimsBuilder construit les claims JWT :

  • sub : identifiant utilisateur
  • email : adresse email
  • role : roles (multiples claims si plusieurs roles)
  • sid : identifiant de session
  • Claims personnalises (permissions, groupes)

JWKS Endpoint

L'endpoint /api/v1/identity/auth/.well-known/jwks.json expose les cles publiques RSA au format JWKS, permettant aux services externes de verifier les tokens sans partager la cle privee.

ProblemDetailsJwtEvents

Gestion personnalisee des erreurs JWT (401, 403) avec format ProblemDetails RFC 7807.

Gestion des sessions

SessionOptions

Defini dans Identity.Infrastructure.Auth.Options.SessionOptions :

OptionDescription
RefreshTokenLifetimeDaysDuree de vie du refresh token en jours
MaxActiveSessionsNombre maximum de sessions actives par utilisateur
EnforceSessionBindingVerifier l'IP et le DeviceId a chaque refresh

Valide au demarrage via SessionOptionsValidator.

SessionService

Implementation combinee de ISessionReader, ISessionWriter et ISessionCleanup :

  • Creation : genere une session avec les informations de l'appareil, le hash du refresh token et la famille de tokens
  • Rotation : met a jour le hash du refresh token, conserve l'ancien hash pour la detection de replay
  • Revocation : marque une session comme revoquee avec une raison
  • Revocation par famille : revoque toutes les sessions d'une famille de tokens (en cas de replay detecte)
  • Nettoyage : supprime les sessions expirees (execute periodiquement)

Services de nettoyage (HostedServices)

ServiceDescription
SessionCleanupHostedServiceNettoyage periodique des sessions expirees
IdempotencyCleanupHostedServiceNettoyage des enregistrements d'idempotence expires
TwoFactorChallengeCleanupHostedServiceNettoyage des challenges 2FA expires
PushTokenCleanupHostedServiceNettoyage des push tokens orphelins
SessionDeviceBindingBootstrapHostedServiceMigration des sessions sans DeviceId

OTP

OtpOptions

Defini dans Identity.Infrastructure.Auth.Options.OtpOptions :

OptionDescription
LengthLongueur du code OTP (defaut: 6 chiffres)
ExpiryMinutesDuree de validite en minutes
MaxAttemptsNombre maximum de tentatives

OtpService

Implementation de IOtpService dans Identity.Infrastructure.Services.OtpService :

  • Genere un code numerique aleatoire de longueur configurable
  • Hash le code avant stockage dans OtpRecord
  • Valide en comparant le hash avec limitation du nombre de tentatives
  • Marque le code comme utilise apres validation reussie

Authentification sociale

SocialAuthOptions

Configuration des providers sociaux :

ProviderOptions
GoogleClientId
FacebookAppId, AppSecret
AppleClientId, KeyId, TeamId

Validateurs de tokens

ValidateurDescription
GoogleTokenValidatorValide les ID tokens Google via Google.Apis.Auth
FacebookTokenValidatorValide les access tokens Facebook via l'API Graph
AppleTokenValidatorValide les ID tokens Apple via les cles publiques Apple

ProviderLinkingService

Gestion de la liaison de comptes sociaux a un compte existant :

  • Verifie qu'un provider n'est pas deja lie a un autre compte
  • Cree un UserLogin avec le ProviderEmail et la date de liaison

Rate Limiting

RateLimitingOptions

Configuration des politiques de rate limiting :

public class RateLimitingOptions
{
    public PolicyOptions Global { get; set; }
    public PolicyOptions Registration { get; set; }
    public PolicyOptions Auth { get; set; }
    public PolicyOptions SessionsRead { get; set; }
    public PolicyOptions SessionsRevoke { get; set; }
    public PolicyOptions AdminSessions { get; set; }
    public PolicyOptions TwoFactor { get; set; }
}

public class PolicyOptions
{
    public int PermitLimit { get; set; }
    public int WindowSeconds { get; set; }
    public int QueueLimit { get; set; }
}

RateLimitPartitionKeyBuilder

Construction des cles de partition pour le rate limiting :

  • Anonyme : partition par adresse IP
  • Authentifie : partition par identifiant utilisateur

RateLimitHeaderWriter

Ecrit les en-tetes standard de rate limiting dans les reponses HTTP :

  • X-RateLimit-Limit : limite de requetes
  • X-RateLimit-Remaining : requetes restantes
  • X-RateLimit-Reset : timestamp de reinitialisation
  • Retry-After : delai avant de reessayer (en cas de 429)

Idempotence

PersistentIdempotencyFilter

Filtre d'endpoint qui assure l'idempotence des requetes POST/PUT :

  1. Verifie la presence d'une cle d'idempotence dans les en-tetes
  2. Cherche un enregistrement existant pour cette cle
  3. Si trouve et non expire : retourne la reponse en cache
  4. Sinon : execute la requete, persiste la reponse dans IdempotencyRecord

Metriques et telemetrie

IdentityMetrics

Metriques OpenTelemetry exposees par le module Identity :

MetriqueDescription
identity.login.successNombre de connexions reussies
identity.login.failureEchecs de connexion par raison (UserNotFound, InvalidPassword, LockedOut, etc.)
identity.registration.successInscriptions reussies
identity.registration.failureEchecs d'inscription par raison
identity.token.refresh.successRefresh tokens reussis
identity.token.refresh.failureEchecs de refresh par raison (ReplayDetected, SessionExpired, etc.)
identity.rate_limit.rejectedRequetes rejetees par rate limiting par politique

AuditMetrics

Metriques du module Audit :

MetriqueDescription
audit.event.persistedEvenements persistes
audit.event.failedEchecs de persistance
audit.write.latencyLatence d'ecriture (ms)

DbContext

IdentityContext

Herite de IdentityDbContext<User, Role, Guid, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>.

DbSets : UserSessions, PasswordHistories, OtpRecords, PushTokens, Groups, GroupRoles, UserGroups, IdempotencyRecords, TwoFactorChallenges, UserSecuritySettings.

Conventions appliquees :

  • FilterSoftDeletedProperties() : filtrage automatique des entites supprimees
  • ToSnakeCaseTables() : convention snake_case
  • ConvertEnumsToStrings() : enums stockes en strings

Support transactionnel complet avec BeginTransactionAsync, CommitTransactionAsync, RollbackTransactionAsync, et ExecuteTransactionalAsync (avec strategie d'execution).

Gestion automatique du versioning via OnBeforeSaving() qui incremente IVersion.Version pour chaque entite modifiee ou supprimee.

AuditContext

Herite de AppDbContextBase. Schema par defaut non specifie (les configurations definissent les schemas au niveau des tables).

DbSets : AuditLogs.

MessagingContext

Herite de AppDbContextBase. Schema : messaging.

DbSets : SentMessages.

Aspire (Orchestration)

Le projet AppHost orchestre l'ensemble de l'infrastructure en developpement :

// PostgreSQL avec 5 bases de donnees
IResourceBuilder<PostgresServerResource> postgres = builder.AddPostgres("postgres")
    .WithImage("postgres", "17");

postgres.AddDatabase("identity");
postgres.AddDatabase("audit");
postgres.AddDatabase("messaging");
postgres.AddDatabase("hangfire");
postgres.AddDatabase("persist-message");

// Mailpit pour les emails en dev
IResourceBuilder<ContainerResource> mailpit = builder.AddContainer("mailpit", "axllent/mailpit");

// API Place
IResourceBuilder<ProjectResource> api = builder.AddProject<Projects.Api>("place-api")
    .WithReference(identityDb)
    .WithReference(auditDb)
    .WithReference(messagingDb)
    .WithHttpEndpoint(5000, null, "api-http")
    .WithHttpsEndpoint(5001, null, "api-https");

// Admin Web (Bun)
builder.AddExecutable("place-admin-web", "bun", adminWebDirectory, "run", "dev")
    .WithReference(api)
    .WithHttpEndpoint(5175, 5175, "http");