Browse Source

Merge pull request #600 from ionite34/fix-lykos-auth

Fix lykos auth api refresh token bugs
pull/629/head
Ionite 7 months ago committed by GitHub
parent
commit
a652287baf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      CHANGELOG.md
  2. 11
      StabilityMatrix.Avalonia/ViewModels/Dialogs/LykosLoginViewModel.cs
  3. 1
      StabilityMatrix.Avalonia/Views/Dialogs/LykosLoginDialog.axaml
  4. 24
      StabilityMatrix.Core/Api/TokenAuthHeaderHandler.cs

3
CHANGELOG.md

@ -6,8 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html).
## v2.10.1 ## v2.10.1
### Changed
- Improved error message when logging in with a Lykos account fails due to incorrect email or password.
### Fixed ### Fixed
- Fixed package launch not working when environment variable `SETUPTOOLS_USE_DISTUTILS` is set due to conflict with a default environment variable. User environment variables will now correctly override any default environment variables. - Fixed package launch not working when environment variable `SETUPTOOLS_USE_DISTUTILS` is set due to conflict with a default environment variable. User environment variables will now correctly override any default environment variables.
- Fixed "No refresh token found" error when failing to login with Lykos account in some cases.
## v2.10.0 ## v2.10.0
### Added ### Added

11
StabilityMatrix.Avalonia/ViewModels/Dialogs/LykosLoginViewModel.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
@ -90,7 +91,15 @@ public partial class LykosLoginViewModel : TaskDialogViewModelBase
} }
catch (ApiException e) catch (ApiException e)
{ {
LoginError = new AppException("Failed to login", $"{e.StatusCode} - {e.Message}"); LoginError = e.StatusCode switch
{
HttpStatusCode.Unauthorized
=> new AppException(
"Incorrect email or password",
"Please try again or reset your password"
),
_ => new AppException("Failed to login", $"{e.StatusCode} - {e.Message}")
};
} }
} }

1
StabilityMatrix.Avalonia/Views/Dialogs/LykosLoginDialog.axaml

@ -14,6 +14,7 @@
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight" xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia" xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia"
Focusable="True" Focusable="True"
MaxWidth="400"
d:DataContext="{x:Static mocks:DesignData.LykosLoginViewModel}" d:DataContext="{x:Static mocks:DesignData.LykosLoginViewModel}"
d:DesignHeight="350" d:DesignHeight="350"
d:DesignWidth="400" d:DesignWidth="400"

24
StabilityMatrix.Core/Api/TokenAuthHeaderHandler.cs

@ -22,8 +22,8 @@ public class TokenAuthHeaderHandler : DelegatingHandler
.HandleResult<HttpResponseMessage>( .HandleResult<HttpResponseMessage>(
r => r =>
r.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden r.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden
&& r.RequestMessage?.Headers.Authorization && r.RequestMessage?.Headers.Authorization is { Scheme: "Bearer", Parameter: { } param }
is { Scheme: "Bearer", Parameter: not null } && !string.IsNullOrWhiteSpace(param)
) )
.RetryAsync( .RetryAsync(
async (result, _) => async (result, _) =>
@ -35,9 +35,7 @@ public class TokenAuthHeaderHandler : DelegatingHandler
"Refreshing access token for status ({StatusCode})", "Refreshing access token for status ({StatusCode})",
result.Result.StatusCode result.Result.StatusCode
); );
var (newToken, _) = await tokenProvider var (newToken, _) = await tokenProvider.RefreshTokensAsync().ConfigureAwait(false);
.RefreshTokensAsync()
.ConfigureAwait(false);
Logger.Info( Logger.Info(
"Access token refreshed: {OldToken} -> {NewToken}", "Access token refreshed: {OldToken} -> {NewToken}",
@ -46,10 +44,6 @@ public class TokenAuthHeaderHandler : DelegatingHandler
); );
} }
); );
// InnerHandler must be left as null when using DI, but must be assigned a value when
// using RestService.For<IMyApi>
// InnerHandler = new HttpClientHandler();
} }
protected override Task<HttpResponseMessage> SendAsync( protected override Task<HttpResponseMessage> SendAsync(
@ -59,9 +53,17 @@ public class TokenAuthHeaderHandler : DelegatingHandler
{ {
return policy.ExecuteAsync(async () => return policy.ExecuteAsync(async () =>
{ {
var accessToken = await tokenProvider.GetAccessTokenAsync().ConfigureAwait(false); // Only add if Authorization is already set to Bearer and access token is not empty
// this allows some routes to not use the access token
if (request.Headers.Authorization is { Scheme: "Bearer" })
{
var accessToken = await tokenProvider.GetAccessTokenAsync().ConfigureAwait(false);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); if (!string.IsNullOrWhiteSpace(accessToken))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}
}
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
}); });

Loading…
Cancel
Save