Rework Refresh Token Storage Solution To Use Windows Credentials API

Minor Version Bump
This commit is contained in:
Alan Moon 2025-09-21 13:49:11 -07:00
parent 4e61a1d7b9
commit d1d3af2ec9
7 changed files with 33 additions and 14 deletions

View File

@ -235,9 +235,9 @@ namespace QtCNETAPI.Services.ApiService
} }
} }
public async Task<ServiceResponse<User>> LoginAsync(UserLoginDto userLoginDto) public async Task<ServiceResponse<string>> LoginAsync(UserLoginDto userLoginDto)
{ {
var serviceResponse = new ServiceResponse<User>(); var serviceResponse = new ServiceResponse<string>();
try try
{ {
@ -257,13 +257,11 @@ namespace QtCNETAPI.Services.ApiService
{ {
SessionToken = response.Data!; SessionToken = response.Data!;
await File.WriteAllTextAsync("./session.token", response.Message);
var user = await SetCurrentUser(); var user = await SetCurrentUser();
serviceResponse.Success = true; serviceResponse.Success = true;
if (response.Message != null) serviceResponse.Message = response.Message; if (response.Message != null) serviceResponse.Message = response.Message;
serviceResponse.Data = user; serviceResponse.Data = response.Message;
} }
else else
{ {

View File

@ -23,7 +23,7 @@ namespace QtCNETAPI.Services.ApiService
public Task<ServiceResponse<List<UserInformationDto>>> GetOnlineUsersAsync(); public Task<ServiceResponse<List<UserInformationDto>>> GetOnlineUsersAsync();
public Task<ServiceResponse<List<UserInformationDto>>> GetAllUsersAsync(); public Task<ServiceResponse<List<UserInformationDto>>> GetAllUsersAsync();
public Task<ServiceResponse<User>> DeleteUserById(string id); public Task<ServiceResponse<User>> DeleteUserById(string id);
public Task<ServiceResponse<User>> LoginAsync(UserLoginDto userLoginDto); public Task<ServiceResponse<string>> LoginAsync(UserLoginDto userLoginDto);
public Task<ServiceResponse<bool>> ResendVerificationEmail(string email); public Task<ServiceResponse<bool>> ResendVerificationEmail(string email);
public Task<ServiceResponse<bool>> SendPasswordResetEmail(string email); public Task<ServiceResponse<bool>> SendPasswordResetEmail(string email);
public Task<ServiceResponse<bool>> ResetPassword(UserPasswordResetDto request); public Task<ServiceResponse<bool>> ResetPassword(UserPasswordResetDto request);

View File

@ -9,12 +9,14 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using qtc_net_client_2.Services;
namespace qtc_net_client_2.Forms namespace qtc_net_client_2.Forms
{ {
public partial class llblForgotPassword : Form public partial class llblForgotPassword : Form
{ {
private IApiService _apiService; private IApiService _apiService;
private CredentialService _credService = new();
public llblForgotPassword(IApiService apiService) public llblForgotPassword(IApiService apiService)
{ {
_apiService = apiService; _apiService = apiService;
@ -24,14 +26,14 @@ namespace qtc_net_client_2.Forms
private async void frmLogin_Load(object sender, EventArgs e) private async void frmLogin_Load(object sender, EventArgs e)
{ {
if (File.Exists("./session.token")) string? accessToken = _credService.GetAccessToken();
if (accessToken != null)
{ {
ToggleControls(false, false); ToggleControls(false, false);
// try logging in with the token in the file // try logging in with the token in cred storage
string token = File.ReadAllText("./session.token"); var result = await _apiService.RefreshLogin(accessToken);
var result = await _apiService.RefreshLogin(token);
if (result.Success) if (result.Success)
{ {
DialogResult = DialogResult.OK; DialogResult = DialogResult.OK;
@ -55,8 +57,9 @@ namespace qtc_net_client_2.Forms
RememberMe = cbRememberMe.Checked RememberMe = cbRememberMe.Checked
}); });
if (result.Success) if (result.Success && result.Data != null)
{ {
_credService.SaveAccessToken(_apiService.CurrentUser.Username, result.Data);
DialogResult = DialogResult.OK; DialogResult = DialogResult.OK;
Close(); Close();
} }

View File

@ -81,7 +81,7 @@ namespace qtc_net_client_2.Properties {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to 6.3.2. /// Looks up a localized string similar to 6.3.3.
/// </summary> /// </summary>
internal static string AssemblyVersion { internal static string AssemblyVersion {
get { get {

View File

@ -173,7 +173,7 @@
<value>..\Icons\MessageIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Icons\MessageIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="AssemblyVersion" xml:space="preserve"> <data name="AssemblyVersion" xml:space="preserve">
<value>6.3.2</value> <value>6.3.3</value>
</data> </data>
<data name="cobalt_sittingatputer" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="cobalt_sittingatputer" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\cobalt_sittingatputer.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\cobalt_sittingatputer.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>

View File

@ -0,0 +1,17 @@
using Meziantou.Framework.Win32;
namespace qtc_net_client_2.Services
{
public class CredentialService()
{
public void SaveAccessToken(string username, string accessToken) => CredentialManager.WriteCredential("QtC.NET", username, accessToken, $"Access Token For User {username} On QtC.NET", CredentialPersistence.LocalMachine);
public string? GetAccessToken()
{
var credential = CredentialManager.ReadCredential("QtC.NET");
if (credential == null) return null;
return credential.Password;
}
}
}

View File

@ -18,6 +18,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Meziantou.Framework.Win32.CredentialManager" Version="1.7.6" />
<PackageReference Include="NAudio" Version="2.2.1" /> <PackageReference Include="NAudio" Version="2.2.1" />
</ItemGroup> </ItemGroup>