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
- Re-export/ re-scan the entry ensuring the full otpauth URI including ?secret=... is captured.
- Verify the QR/URI contains a non-empty secret parameter before attempting import.
- If the source redacted the secret, obtain the unredacted original from the authenticator.
- 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
- Validate presence AND non-empty length of 'secret' before importing.
- Pre-flight check that the URI includes a '?' and a 'secret=' key.
- Warn when a QR scan returns a suspiciously short string (likely truncated).
- Collect all missing-field errors per entry and report them together.
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Import only supports otpauth://
- Import only supports otpauth://totp/ or otpauth://hotp/
- HOTP authenticator should have a counter
- Battle.net Authenticator does not have a serial
- Invalid serial for Battle.net Authenticator
AI-assisted analysis of BeyondDimension/SteamTools@c16ffa08e0 (2026-08-13).
Data as JSON: /api/errors/0f245289386a5766.
Report an issue: GitHub.