/*
* 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 ProtonVPN.Api.Contracts;
using ProtonVPN.Api.Contracts.Auth;
using ProtonVPN.Client.Settings.Contracts;
using ProtonVPN.Logging.Contracts;
using ProtonVPN.Logging.Contracts.Events.ApiLogs;
using ProtonVPN.Logging.Contracts.Events.UserLogs;
namespace ProtonVPN.Client.Logic.Auth;
public class UnauthSessionManager : IUnauthSessionManager
{
private readonly ILogger _logger;
private readonly IApiClient _apiClient;
private readonly ISettings _settings;
private readonly SemaphoreSlim _semaphore = new(1, 1);
public UnauthSessionManager(ILogger logger, IApiClient apiClient, ISettings settings)
{
_logger = logger;
_apiClient = apiClient;
_settings = settings;
}
public async Task CreateIfDoesNotExistAsync(CancellationToken cancellationToken)
{
await _semaphore.WaitAsync(cancellationToken);
try
{
if (IsUnauthSessionCreated())
{
return;
}
_logger.Info("Requesting unauth session to initiate login process.");
ApiResponseResult unauthSessionResponse = await _apiClient.PostUnauthSessionAsync(cancellationToken);
if (unauthSessionResponse.Success)
{
SaveUnauthSessionDetails(unauthSessionResponse.Value);
}
}
catch (Exception ex)
{
_logger.Error("An error occurred when requesting a new unauth session.", ex);
}
finally
{
_semaphore.Release();
}
}
private bool IsUnauthSessionCreated()
{
return _settings.UnauthUniqueSessionId != null
&& _settings.UnauthAccessToken != null
&& _settings.UnauthRefreshToken != null;
}
private void SaveUnauthSessionDetails(UnauthSessionResponse response)
{
_settings.UnauthUniqueSessionId = response.UniqueSessionId;
_settings.UnauthAccessToken = response.AccessToken;
_settings.UnauthRefreshToken = response.RefreshToken;
}
public void Revoke()
{
_settings.UnauthUniqueSessionId = null;
_settings.UnauthAccessToken = null;
_settings.UnauthRefreshToken = null;
}
public async Task RecreateAsync(CancellationToken cancellationToken)
{
Revoke();
await CreateIfDoesNotExistAsync(cancellationToken);
}
}