Files
Libation/Source/AudibleUtilities/AccountCredentialStatus.cs
T
Cursor Agentandrmcrackan 337cb3169a Adopt Dinah.Core 10.2.2.1 and AudibleApi 11.0.0.1
AudibleApi 11 holds token, key, and cookie values in a SecretString
rather than a string, so nothing public exposes plaintext for a reflective
logger to find. Picking it up is a breaking upgrade: the seven package
references move, and the nine places that read a secret now call Reveal().

Two of those needed thought rather than a mechanical edit. Mkb79Auth
exports to and imports from audible-cli's JSON format, which is plaintext
by definition, so the cookie projections reveal explicitly in both
directions and the file format is unchanged. And the account's own
DecryptKey stays a plain string here: converting it is separate work.

This is the dependency bump only. The log leak it enables fixing - an
AuthenticationRequiredException carrying a live Account, whose address and
activation bytes Serilog.Exceptions writes into a shared log - is still
open, and none of the account-side masking has landed yet.

Co-authored-by: rmcrackan <rmcrackan@gmail.com>
2026-08-17 01:49:21 +00:00

38 lines
1.3 KiB
C#

using Dinah.Core;
namespace AudibleUtilities;
/// <summary>Describes whether an account has usable stored Audible tokens.</summary>
public static class AccountCredentialStatus
{
/// <summary>
/// True when identity tokens are absent or carry no refresh token, meaning the account was never fully logged
/// in or its credentials were cleared, rather than merely holding an expired access token.
/// </summary>
public static bool LooksLikeMissingCredentials(Account? account)
{
if (account?.IdentityTokens is not { } tokens)
return true;
if (tokens.IsValid)
return false;
// without a refresh token there is nothing to renew from, so this needs a fresh login rather than a retry
return string.IsNullOrWhiteSpace(tokens.RefreshToken?.Reveal());
}
/// <summary>
/// Account label for dialogs shown to the person who owns the account. Not for logs: those get attached to
/// public issue reports, which is what <see cref="Account.MaskedLogEntry"/> is for.
/// </summary>
public static string FormatAccountLabel(Account? account)
{
if (account is null)
return "an Audible account";
return string.IsNullOrWhiteSpace(account.AccountName) || account.AccountName.EqualsInsensitive(account.AccountId)
? $"'{account.AccountId}'"
: $"'{account.AccountName}' ({account.AccountId})";
}
}