using System.Collections.Generic; using System.Security.Claims; using GB5Shared.Auth.Jwt; namespace DXPBLL.Auth; public class DXPAccessTokenClaims : IJwtClaimsSource { public int DxpUserId { get; set; } public int DxpPartyId { get; set; } public int TenantId { get; set; } public string DatabaseName { get; set; } = string.Empty; public byte DatabaseType { get; set; } public int LocalPartyId { get; set; } public string RoleCode { get; set; } = string.Empty; public IEnumerable ToClaims() => new[] { new Claim(DXPClaimTypes.DxpUserId, DxpUserId.ToString()), new Claim(DXPClaimTypes.DxpPartyId, DxpPartyId.ToString()), new Claim(DXPClaimTypes.TenantId, TenantId.ToString()), new Claim(DXPClaimTypes.DatabaseName, DatabaseName), new Claim(DXPClaimTypes.DatabaseType, DatabaseType.ToString()), new Claim(DXPClaimTypes.LocalPartyId, LocalPartyId.ToString()), new Claim(DXPClaimTypes.RoleCode, RoleCode) }; } public class DXPTokenPair { public string AccessToken { get; set; } = string.Empty; public DateTime AccessTokenExpiresOn { get; set; } public string RefreshToken { get; set; } = string.Empty; // raw refresh token — returned to the client once, never stored raw server-side public DateTime RefreshTokenExpiresOn { get; set; } } // Issues/validates DXP's own signed session — see Part 2 of the DXP plan. Access tokens are // short-lived JWTs; refresh tokens are opaque random strings whose SHA-256 hash is the only // thing persisted (MDXPREFRESHTOKEN.TokenHash), so a DB leak never exposes a usable token. public interface IDXPJwtService { Task IssueAccessTokenAsync(DXPAccessTokenClaims claims, CancellationToken ct); /// Issues a full access+refresh pair in one call, both expiries computed exactly /// once — the structural fix for AuthBLL's former hardcoded-15/30 drift bug. Task IssueTokenPairAsync(DXPAccessTokenClaims claims, CancellationToken ct); (string RawToken, string TokenHash) GenerateRefreshToken(); string HashRefreshToken(string rawToken); }