fail quick connect closed on an unreachable valkey and restore the idempotent exchange
This commit is contained in:
@@ -141,7 +141,7 @@ namespace Emby.Server.Implementations.QuickConnect
|
||||
|
||||
if (result.Authenticated)
|
||||
{
|
||||
throw new InvalidOperationException("Request is already authorized");
|
||||
throw new ConflictException("Request is already authorized");
|
||||
}
|
||||
|
||||
// Change the time on the request so it expires one minute into the future. It can't expire immediately as otherwise some clients wouldn't ever see that they have been authenticated.
|
||||
@@ -150,7 +150,7 @@ namespace Emby.Server.Implementations.QuickConnect
|
||||
// The guard above is a read on shared state, so it cannot settle a race between instances; the claim can.
|
||||
if (!await _store.TryClaimAuthorizationAsync(result.Secret, ExpiryOf(result)).ConfigureAwait(false))
|
||||
{
|
||||
throw new InvalidOperationException("Request is already authorized");
|
||||
throw await RefusedClaimAsync(result.Secret).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var authenticationResult = await _sessionManager.AuthenticateDirect(new AuthenticationRequest
|
||||
@@ -177,7 +177,7 @@ namespace Emby.Server.Implementations.QuickConnect
|
||||
{
|
||||
AssertActive();
|
||||
|
||||
var result = await _store.TryConsumeAuthorizationAsync(secret).ConfigureAwait(false);
|
||||
var result = await _store.GetAuthorizationAsync(secret).ConfigureAwait(false);
|
||||
if (result is null)
|
||||
{
|
||||
throw new ResourceNotFoundException("Unable to find request");
|
||||
@@ -188,6 +188,20 @@ namespace Emby.Server.Implementations.QuickConnect
|
||||
|
||||
private static DateTime ExpiryOf(QuickConnectResult request) => request.DateAdded.AddMinutes(Timeout);
|
||||
|
||||
/// <summary>
|
||||
/// Explains a refused claim. The claim outlives a failed mint on purpose, so it can mean either
|
||||
/// that the request is authorized or that authorizing it did not finish; the two are told apart
|
||||
/// by re-reading the request rather than reported as the same thing.
|
||||
/// </summary>
|
||||
private async Task<ConflictException> RefusedClaimAsync(string secret)
|
||||
{
|
||||
var current = await _store.GetRequestBySecretAsync(secret).ConfigureAwait(false);
|
||||
|
||||
return current?.Authenticated == true
|
||||
? new ConflictException("Request is already authorized")
|
||||
: new ConflictException("Request is being authorized elsewhere, or an earlier attempt to authorize it did not complete. Start quick connect again for a new code.");
|
||||
}
|
||||
|
||||
private string GenerateSecureRandom(int length = 32)
|
||||
{
|
||||
Span<byte> bytes = stackalloc byte[length];
|
||||
|
||||
Reference in New Issue
Block a user