BeyondDimension/SteamTools · warning · ApplicationException

Authenticator does not contain secret

Error message

Authenticator does not contain secret

What it means

Thrown when an otpauth URI has no 'secret' query parameter (or it is empty). The secret is the base32-encoded shared key required to generate codes, so without it the entry is unusable and import aborts at the secret check.

Source

Thrown at src/BD.WTTS.Client.Plugins.Authenticator/UI/ViewModels/AuthenticatorImportPageViewModel.cs:294

                string issuer = string.Empty;
                string label = string.IsNullOrEmpty(uri.LocalPath) == false
                    ? uri.LocalPath[1..]
                    : string.Empty; // skip past initial /
                int p = label.IndexOf(":", StringComparison.Ordinal);
                if (p != -1)
                {
                    issuer = label.Substring(0, p);
                    label = label[(p + 1)..];
                }

                // + aren't decoded
                label = label.Replace("+", " ");

                var query = HttpUtility.ParseQueryString(uri.Query);
                string? secret = query["secret"];
                if (string.IsNullOrEmpty(secret))
                {
                    throw new ApplicationException("Authenticator does not contain secret");
                }

                string? counter = query["counter"];
                if (uri.Host == "hotp" && string.IsNullOrEmpty(counter))
                {
                    throw new ApplicationException("HOTP authenticator should have a counter");
                }

                AuthenticatorDTO authenticatorDto = new();

                AuthenticatorValueDTO auth;
                if (string.Compare(issuer, "BattleNet", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    string? serial = query["serial"];
                    if (string.IsNullOrEmpty(serial))
                    {
                        throw new ApplicationException("Battle.net Authenticator does not have a serial");
                    }

View on GitHub (pinned to c16ffa08e0)

Solutions

  1. Re-export/ re-scan the entry ensuring the full otpauth URI including ?secret=... is captured.
  2. Verify the QR/URI contains a non-empty secret parameter before attempting import.
  3. If the source redacted the secret, obtain the unredacted original from the authenticator.
  4. Show a field-level validation error in the UI naming the missing parameter.

Example fix

// before
string? secret = query["secret"];
if (string.IsNullOrEmpty(secret))
    throw new ApplicationException("Authenticator does not contain secret");

// after: validate length too (base32 secret should be >= 16 chars)
string? secret = query["secret"];
if (string.IsNullOrWhiteSpace(secret) || secret.Length < 16)
    throw new ArgumentException(Strings.Import_MissingOrShortSecret);
Defensive patterns

Strategy: validation

Validate before calling

var query = HttpUtility.ParseQueryString(uri.Query);
var secret = query["secret"];
if (string.IsNullOrWhiteSpace(secret))
    errors.Add(($"Line {n}: missing 'secret' parameter.", line));
else if (secret.Length < 16)
    errors.Add(($"Line {n}: 'secret' too short (base32 expected >= 16 chars).", line));

Type guard

bool HasValidSecret(Uri u) => !string.IsNullOrWhiteSpace(HttpUtility.ParseQueryString(u.Query)["secret"]);

Try / catch

try { ParseAuthenticator(line); }
catch (ApplicationException ex) when (ex.Message == "Authenticator does not contain secret")
{
    importErrors.Add(($"Missing secret (line {n}).", line));
    continue;
}

Prevention

When it happens

Trigger: Parsing otpauth://totp/... or ...://hotp/... where the query string has no 'secret' key, or its value is empty — e.g. a truncated URI, a malformed QR, or an export that omitted the secret.

Common situations: QR code was cropped/truncated losing the query string; export tool redacted the secret for safety; URI was hand-typed and the secret forgotten; encoding bug stripped the '?' or query.

Understand the failure class

Related errors


AI-assisted analysis of BeyondDimension/SteamTools@c16ffa08e0 (2026-08-13). Data as JSON: /api/errors/0f245289386a5766. Report an issue: GitHub.