/* * 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.Logic.Auth.Contracts.Enums; using ProtonVPN.Client.Logic.Auth.Contracts.Models; using ProtonVPN.Client.Settings.Contracts; using ProtonVPN.Logging.Contracts; using ProtonVPN.Logging.Contracts.Events.UserLogs; namespace ProtonVPN.Client.Logic.Auth; public class SsoAuthenticator : AuthenticatorBase, ISsoAuthenticator { private const string SSO_LOGIN_INTENT = "SSO"; private readonly IApiClient _apiClient; private readonly ILogger _logger; private readonly IUnauthSessionManager _unauthSessionManager; public SsoAuthenticator( IApiClient apiClient, ISettings settings, ILogger logger, IUnauthSessionManager unauthSessionManager) : base(settings) { _apiClient = apiClient; _logger = logger; _unauthSessionManager = unauthSessionManager; } public async Task StartSsoAuthAsync(string username, CancellationToken cancellationToken) { await _unauthSessionManager.CreateIfDoesNotExistAsync(cancellationToken); AuthInfoRequest infoRequest = new() { Username = username, Intent = SSO_LOGIN_INTENT }; ApiResponseResult authInfoResponse = await _apiClient.GetAuthInfoResponse(infoRequest, cancellationToken); if (!authInfoResponse.Success || string.IsNullOrEmpty(authInfoResponse.Value?.SsoChallengeToken)) { _logger.Error("Failed to login with SSO."); return SsoAuthResult.FromAuthResult(AuthResult.Fail(authInfoResponse)); } return SsoAuthResult.Ok(authInfoResponse.Value.SsoChallengeToken); } public async Task CompleteSsoAuthAsync(string ssoResponseToken, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(ssoResponseToken)) { return AuthResult.Fail(AuthError.SsoAuthFailed); } AuthRequest authRequest = new() { SsoResponseToken = ssoResponseToken, }; ApiResponseResult authResponse = await _apiClient.GetAuthResponse(authRequest, cancellationToken); if (authResponse.Failure) { return AuthResult.Fail(authResponse); } SaveAuthSessionDetails(authResponse.Value); return AuthResult.Ok(); } }