/*
* Copyright (c) 2025 Proton AG
*
* This file is part of ProtonVPN.
*
* ProtonVPN is free software:
you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonVPN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonVPN. If not, see .
*/
using System.Net;
using System.Security;
using System.Text.Json;
using ProtonVPN.Client.Logic.Auth.Contracts;
using ProtonVPN.Client.Logic.Auth.Contracts.Models;
using RichardSzalay.MockHttp;
namespace ProtonVPN.Integration.Tests;
public class AuthenticatedUserTests : TestBase
{
protected const string CORRECT_PASSWORD = "password";
protected const string WRONG_PASSWORD = "wrong";
protected const string CERTIFICATE =
"-----BEGIN CERTIFICATE-----\n" +
"MIICEzCCAcWgAwIBAgICA6QwBQYDK2VwMDgxNjA0BgNVBAMMLVByb3RvblZQTiBD\n" +
"bGllbnQgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDE3ODYxMzAeFw0yMjA2MzAwOTIy\n" +
"NDZaFw0yMjA3MDEwOTIyNDdaMA4xDDAKBgNVBAMMAzkzMjAqMAUGAytlcAMhAIRl\n" +
"nVhh8k5SlmSWqEjvaLnghx2z01fD/jWtWikfyJ3oo4IBGzCCARcwHQYDVR0OBBYE\n" +
"FD2ziAiZ58wvQokqBl/YrHX3rU9gMBMGDCsGAQQBg7tpAQAAAAQDAgEAMBMGDCsG\n" +
"AQQBg7tpAQAAAQQDAgEAMBwGDCsGAQQBg7tpAQAAAgQMMAoECHZwbi1mcmVlMBkG\n" +
"DCsGAQQBg7tpAQAAAwQJBAdXaW5kb3dzMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB\n" +
"Af8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMCMGAGA1UdIwRZMFeAFAM/RhKQDNy0\n" +
"eNyeSWDEioh6Rv1goTykOjA4MTYwNAYDVQQDDC1Qcm90b25WUE4gQ2xpZW50IENl\n" +
"cnRpZmljYXRlIEF1dGhvcml0eSAxNzg2MTOCAQIwBQYDK2VwA0EATuIkjDSzmZa5\n" +
"UIfgGDGcNvFTVQBxSNzmGgZ+8YS60asMpo2vlGOyuy1U8vb3PsHSRYIgnJVup0P0\n" +
"aFJlft9QCg==\n" +
"-----END CERTIFICATE-----\n";
protected void SetApiResponsesForAuth()
{
SetAuthInfoResponse();
SetAuthResponse();
SetVpnInfoResponse();
SetAuthCertificateResponse();
SetUserResponse();
SetIpv6ragmentsResponse();
}
protected void SetApiResponsesForAuthWithTwoFactor()
{
SetAuthInfoResponse();
SetAuthResponseWithTwoFactorEnabled();
}
private void SetAuthInfoResponse()
{
MessageHandler!.When(HttpMethod.Post, "/auth/info").Respond(_ => new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(GetJsonMock("AuthInfoResponseMock"))
});
}
private void SetAuthResponse()
{
string responseBody = GetJsonMock("AuthResponseMock");
SetExpectedServerProof(CORRECT_PASSWORD, responseBody);
MessageHandler!.When(HttpMethod.Post, "/auth").Respond(_ => new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(responseBody)
});
}
private void SetAuthResponseWithTwoFactorEnabled()
{
string responseBody = GetJsonMock("AuthResponseWithTwoFactorEnabledMock");
SetExpectedServerProof(CORRECT_PASSWORD, responseBody);
MessageHandler!.When(HttpMethod.Post, "/auth").Respond(_ => new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(responseBody)
});
}
private void SetVpnInfoResponse()
{
MessageHandler!.When(HttpMethod.Get, "/vpn/v2").Respond(_ => new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(GetJsonMock("VpnInfoWrapperResponseMock"))
});
}
private void SetAuthCertificateResponse()
{
MessageHandler!.When(HttpMethod.Post, "/vpn/v1/certificate").Respond(_ => new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(GetJsonMock("CertificateResponseMock"))
});
}
private void SetUserResponse()
{
MessageHandler!.When(HttpMethod.Get, "/core/v4/users").Respond(_ => new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(GetJsonMock("UserResponseMock"))
});
}
private void SetIpv6ragmentsResponse()
{
MessageHandler!.When(HttpMethod.Get, "/vpn/v1/ipv6-fragments").Respond(_ => new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(GetJsonMock("IPv6FragmentsResponseMock"))
});
}
private void SetExpectedServerProof(string password, string responseBody)
{
using JsonDocument document = JsonDocument.Parse(responseBody);
if (document.RootElement.TryGetProperty("ServerProof", out JsonElement serverProofProperty))
{
string? expectedServerProof = serverProofProperty.GetString();
if (!string.IsNullOrEmpty(expectedServerProof))
{
SrpProofGenerator.SetExpectedServerProof(password, expectedServerProof);
}
}
}
protected async Task MakeUserAuthAsync(string password)
{
SecureString securePassword = new NetworkCredential("", password).SecurePassword;
return await Resolve().LoginUserAsync("username", securePassword);
}
}