using EntitlementBLL.Auth; using FastEndpoints; using GB5Shared.DTO.Framework.Login; using GB5Shared.DTO.Framework.ResponseStandard; using GB5Shared.FastEndPoint; using GB5Shared.Resource.Response; using static GB5Shared.GB5Constant.Constant; namespace EntitlementSL.Endpoints.ClientAuth; // AllowAnonymous — same trust model as RefreshToken.cs: the presented refresh token is the // credential, not a bearer access token. ClientAuthBLL.LogoutAsync performs a plain, idempotent // revoke (ReplacedByTokenId left null) and deliberately never routes this through the // reuse-detection cascade — a voluntary logout is not a theft signal. Always returns success, even // for an unknown or already-revoked token, so a client can never distinguish "already logged out" // from "logged out just now." public class Logout : BaseEndpoint> { private readonly IClientAuthBLL _ClientAuthBLL; public Logout(IClientAuthBLL clientAuthBLL) => _ClientAuthBLL = clientAuthBLL; public override void Configure() { Post("/lic/ClientAuth.svc/Logout"); AllowAnonymous(); } public record Body(string RawRefreshToken); public record Params( [property: FromHeader] string Login, [property: FromBody] Body RequestBody ); protected override string? GetCacheKey(Params req, LoginDTO loginDTO) => null; protected override async Task> ExecuteAsync(Params req, LoginDTO loginDTO, CancellationToken ct) { await _ClientAuthBLL.LogoutAsync(req.RequestBody.RawRefreshToken, loginDTO, ct); return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse( SuccessResponse.LogoutSuccessMessage, CacheKeyLevel.NOT_REQUIRED, loginDTO); } }