88 lines
3.2 KiB
C#
88 lines
3.2 KiB
C#
|
|
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;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// /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.
|
|||
|
|
/// </summary>
|
|||
|
|
public class PlatformSessionRevocationHandler :
|
|||
|
|
IOpenIddictServerHandler<HandleRevocationRequestContext>,
|
|||
|
|
ITransientDependency
|
|||
|
|
{
|
|||
|
|
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
|
|||
|
|
= OpenIddictServerHandlerDescriptor
|
|||
|
|
.CreateBuilder<HandleRevocationRequestContext>()
|
|||
|
|
.UseScopedHandler<PlatformSessionRevocationHandler>()
|
|||
|
|
.SetOrder(int.MaxValue - 10)
|
|||
|
|
.SetType(OpenIddictServerHandlerType.Custom)
|
|||
|
|
.Build();
|
|||
|
|
|
|||
|
|
private readonly IIdentitySessionRepository sessionRepo;
|
|||
|
|
private readonly ICurrentTenant currentTenant;
|
|||
|
|
private readonly ILogger<PlatformSessionRevocationHandler> logger;
|
|||
|
|
|
|||
|
|
public PlatformSessionRevocationHandler(
|
|||
|
|
IIdentitySessionRepository sessionRepo,
|
|||
|
|
ICurrentTenant currentTenant,
|
|||
|
|
ILogger<PlatformSessionRevocationHandler> 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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|