diff --git a/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/AuthApiClientIntegrationTests.cs b/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/AuthApiClientIntegrationTests.cs new file mode 100644 index 0000000..eb1928d --- /dev/null +++ b/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/AuthApiClientIntegrationTests.cs @@ -0,0 +1,111 @@ +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; +using JdeScoping.Client.Services; +using JdeScoping.Core.Models.Auth; +using Microsoft.AspNetCore.Mvc.Testing; +using Shouldly; + +namespace JdeScoping.Api.IntegrationTests.ClientIntegration; + +public class AuthApiClientIntegrationTests : ClientIntegrationTestBase +{ + public AuthApiClientIntegrationTests(TestWebApplicationFactory factory) : base(factory) { } + + [Fact] + public async Task GetPublicKeyAsync_ReturnsValidPublicKey() + { + // Act + var result = await AuthClient.GetPublicKeyAsync(); + + // Assert + result.IsSuccess.ShouldBeTrue(); + result.Value.PublicKeyPem.ShouldStartWith("-----BEGIN PUBLIC KEY-----"); + } + + [Fact] + public async Task LoginAsync_WithValidCredentials_ReturnsSuccess() + { + // Arrange - get public key and encrypt credentials + var publicKeyResult = await AuthClient.GetPublicKeyAsync(); + publicKeyResult.IsSuccess.ShouldBeTrue(); + + var loginModel = new LoginModel { Username = "testuser", Password = "testpass" }; + var json = JsonSerializer.Serialize(loginModel); + var plaintext = Encoding.UTF8.GetBytes(json); + + using var rsa = RSA.Create(); + rsa.ImportFromPem(publicKeyResult.Value.PublicKeyPem); + var ciphertext = rsa.Encrypt(plaintext, RSAEncryptionPadding.OaepSHA256); + + var encryptedRequest = new EncryptedLoginRequest(Convert.ToBase64String(ciphertext)); + + // Act + var result = await AuthClient.LoginAsync(encryptedRequest); + + // Assert + result.IsSuccess.ShouldBeTrue(); + result.Value.Success.ShouldBeTrue(); + result.Value.User.ShouldNotBeNull(); + result.Value.User.Username.ShouldBe("testuser"); + } + + [Fact] + public async Task GetCurrentUserAsync_AfterLogin_ReturnsUserInfo() + { + // Arrange + await LoginAsync(); + + // Act + var result = await AuthClient.GetCurrentUserAsync(); + + // Assert + result.IsSuccess.ShouldBeTrue(); + result.Value.Username.ShouldBe("testuser"); + } + + [Fact] + public async Task GetCurrentUserAsync_WithoutAuth_ReturnsUnauthorized() + { + // Arrange - use fresh client without cookies + var freshClient = new AuthApiClient(CreateFreshClient()); + + // Act + var result = await freshClient.GetCurrentUserAsync(); + + // Assert + result.IsUnauthorized.ShouldBeTrue(); + } + + [Fact] + public async Task LogoutAsync_AfterLogin_InvalidatesSession() + { + // Arrange - create fresh client for this test to avoid affecting other tests + var client = Factory.CreateClient(new WebApplicationFactoryClientOptions + { + HandleCookies = true, + AllowAutoRedirect = false + }); + var authClient = new AuthApiClient(client); + + // Login first + var publicKeyResult = await authClient.GetPublicKeyAsync(); + var loginModel = new LoginModel { Username = "testuser", Password = "testpass" }; + var json = JsonSerializer.Serialize(loginModel); + using var rsa = RSA.Create(); + rsa.ImportFromPem(publicKeyResult.Value.PublicKeyPem); + var ciphertext = rsa.Encrypt(Encoding.UTF8.GetBytes(json), RSAEncryptionPadding.OaepSHA256); + await authClient.LoginAsync(new EncryptedLoginRequest(Convert.ToBase64String(ciphertext))); + + // Verify login worked + var beforeLogout = await authClient.GetCurrentUserAsync(); + beforeLogout.IsSuccess.ShouldBeTrue(); + + // Act - call logout (server returns 200 OK with empty body) + await authClient.LogoutAsync(); + + // Assert - verify session is invalidated (me endpoint should return unauthorized) + var meResult = await authClient.GetCurrentUserAsync(); + meResult.IsUnauthorized.ShouldBeTrue(); + } +}