signalapp/Signal-Server · error · BadRequestException
Operation requires unauthenticated access
Error message
Operation requires unauthenticated access
What it means
requireNotAuthenticated enforces that username-hash lookup, username-link lookup, and account-existence checks are only performed anonymously. If the request carries credentials for an authenticated device, the server throws BadRequestException('Operation requires unauthenticated access') to prevent accounts from probing other usernames while logged in.
Solutions
- Issue these lookups from an unauthenticated client that does not attach the Authorization header.
- Configure the HTTP client to strip credentials for anonymous endpoints.
- Use a separate, credential-free client instance for username lookup/account-existence probes.
Example fix
// before
httpClient.get("/v1/accounts/username_hash/" + hash, withAuthHeader(token));
// after
anonymousHttpClient.get("/v1/accounts/username_hash/" + hash); // no Authorization header Defensive patterns
Strategy: validation
Validate before calling
if (request.headers['authorization']) throw new Error('strip Authorization header for anonymous lookups'); Type guard
const isAnonymousRequest = (opts) => opts.headers && !('Authorization' in opts.headers); Try / catch
try { return await lookupUsernameHash(hash); } catch (e) { if (e.status === 400 && e.message.includes('unauthenticated access')) { return anonymousClient.lookupUsernameHash(hash); } throw e; } Prevention
- Use a separate client instance without credential injection for anonymous endpoints
- Audit HTTP interceptors that auto-attach auth tokens
- Document which endpoints must remain unauthenticated
When it happens
Trigger: Calling GET /v1/accounts/username_hash/{hash}, GET /v1/accounts/username_link/{uuid}, or the account-exists endpoint while including an Authorization header / authenticated device credentials.
Common situations: Shared HTTP client that automatically attaches the auth token to every request, SDK wrappers that inject credentials globally, or tests replaying an authenticated session for anonymous lookups.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- must not use authenticated connection for anonymous…
- may not provide both group send token and unidentified…
- account does not have a phone number
- recovery password could not be verified
- must not use authenticated connection for call quality…
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/4951887998e8903c.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java:542
}
private void clearUsernameLink(final UUID accountIdentifier) {
updateUsernameLink(accountIdentifier, null, null);
}
private void updateUsernameLink(
final UUID accountIdentifier,
@Nullable final UUID usernameLinkHandle,
@Nullable final byte[] encryptedUsername) {
if ((encryptedUsername == null) ^ (usernameLinkHandle == null)) {
throw new IllegalStateException("Both or neither arguments must be null");
}
accounts.update(accountIdentifier, a -> a.setUsernameLinkDetails(usernameLinkHandle, encryptedUsername));
}
private void requireNotAuthenticated(final Optional<AuthenticatedDevice> authenticatedAccount) {
if (authenticatedAccount.isPresent()) {
throw new BadRequestException("Operation requires unauthenticated access");
}
}
}
View on GitHub (pinned to 100ab61c82)