using System; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using OpenIddict.Abstractions; using OpenIddict.Server; using static OpenIddict.Server.OpenIddictServerEvents; using Volo.Abp.DependencyInjection; using Volo.Abp.Identity; using Volo.Abp.MultiTenancy; using Volo.Abp.Security.Claims; namespace Sozsoft.Platform.Identity; /// /// /connect/revocation çağrısı başarıyla tamamlandığında ilgili kullanıcının /// AbpSessions tablosundaki tüm satırlarını siler. /// OpenIddict server pipeline'ına eklenir; MVC controller override gerektirmez. /// public class PlatformSessionRevocationHandler : IOpenIddictServerHandler, ITransientDependency { public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor .CreateBuilder() .UseScopedHandler() .SetOrder(int.MaxValue - 10) .SetType(OpenIddictServerHandlerType.Custom) .Build(); private readonly IIdentitySessionRepository sessionRepo; private readonly ICurrentTenant currentTenant; private readonly ILogger logger; public PlatformSessionRevocationHandler( IIdentitySessionRepository sessionRepo, ICurrentTenant currentTenant, ILogger logger) { this.sessionRepo = sessionRepo; this.currentTenant = currentTenant; this.logger = logger; } public async ValueTask HandleAsync(HandleRevocationRequestContext context) { // Hata durumunda (geçersiz token, yetkisiz istek vb.) temizlik yapma. if (context.IsRejected) return; var userId = context.Principal?.GetClaim(OpenIddictConstants.Claims.Subject); if (string.IsNullOrEmpty(userId) || !Guid.TryParse(userId, out var userGuid)) return; // Token'dan tenant ID'yi al. var tenantIdStr = context.Principal?.GetClaim(AbpClaimTypes.TenantId); Guid? tenantId = null; if (!string.IsNullOrWhiteSpace(tenantIdStr) && Guid.TryParse(tenantIdStr, out var parsedTenantId)) { tenantId = parsedTenantId; } try { // Sadece token'ın ait olduğu tenant'taki oturumları sil. using (currentTenant.Change(tenantId)) { var sessions = await sessionRepo.GetListAsync(userId: userGuid); foreach (var session in sessions) { await sessionRepo.DeleteAsync(session); } if (sessions.Count > 0) { logger.LogInformation( "Token revocation: {Count} IdentitySession silindi. UserId: {UserId}, TenantId: {TenantId}", sessions.Count, userGuid, tenantId); } } } catch (Exception ex) { // Session temizleme hatası revocation akışını bloklamamalı. logger.LogWarning(ex, "Token revocation sonrası IdentitySession temizliğinde hata. UserId: {UserId}", userId); } } }