Companion App: "app pass cannot be empty" on password-requiring actions
Summary
Several API endpoints require the app password but the frontend does not
include it in the request body. Instead, the server falls back to a
cached password looked up via cookies (authCK + pwKeyCK). When the
companion app (Android/GeckoView over tor) makes these requests, the
cookies are either not set or not transmitted, causing resolvePass to
return "app pass cannot be empty".
Reproduction
- Pair a companion app via QR code.
- Log in on the companion app.
- Navigate to the trade view and click "Create Account" for a new DEX.
- Error modal appears:
"password error: app pass cannot be empty".
Root cause
resolvePass (client/webserver/api.go:2339) checks for a password in
two places:
- The request body (
appPW / pass field).
- The cookie-based cache (
getCachedPasswordUsingRequest).
The cookies are set during login (actuallyLogin, line 1596-1602) with
SameSite=Strict. GeckoView on Android, connecting via a .onion
address, may not persist or send these cookies on subsequent requests.
Affected endpoints
The following frontend calls send no password field in the request
body, relying entirely on the cookie cache. All of these will fail from
the companion app:
| API endpoint |
Frontend location |
Action |
/api/postbond |
forms.ts:837 |
Create Account / post bond |
/api/discoveracct |
forms.ts:1732 |
Discover existing account |
/api/openwallet |
dexsettings.ts:207, markets.ts:2263, wallets.ts:2260 |
Unlock wallet |
/api/tradeasync |
markets.ts:2819 |
Place a trade |
/api/accelerateorder |
forms.ts:1481 |
Accelerate order |
/api/exportaccount |
dexsettings.ts:300 |
Export account |
/api/importaccount |
settings.ts:380 |
Import account |
/api/toggleaccountstatus |
dexsettings.ts:325 |
Disable/enable account |
/api/configuremixer |
wallets.ts:1756 |
Toggle mixing |
/api/startmarketmakingbot |
mmutil.ts:128 |
Start market maker bot |
/api/redeemprepaidbond |
forms.ts:1166 |
Redeem prepaid bond |
/api/redeemgamecode |
settings.ts:523 |
Redeem game code |
Not affected
These endpoints receive the password from the frontend form (e.g. during
initial setup or explicit password prompts):
/api/login - password entered on login form
/api/newwallet (from init.ts) - password passed during setup
/api/adddex (from init.ts) - password passed during setup
Possible fixes
-
Server-side: For companion app (onion) requests, look up the
cached password by companion token instead of by cookie. The server
already knows which companion token is paired and could maintain a
password cache keyed by that token.
-
Frontend: Ensure the password cookies are included in all
postJSON requests from GeckoView by adjusting cookie settings
(e.g. SameSite=None for onion requests, or using credentials: include in fetch calls).
-
GeckoView config: Investigate whether GeckoView's cookie storage
or privacy settings are stripping cookies on .onion domains.
Companion App: "app pass cannot be empty" on password-requiring actions
Summary
Several API endpoints require the app password but the frontend does not
include it in the request body. Instead, the server falls back to a
cached password looked up via cookies (
authCK+pwKeyCK). When thecompanion app (Android/GeckoView over tor) makes these requests, the
cookies are either not set or not transmitted, causing
resolvePasstoreturn
"app pass cannot be empty".Reproduction
"password error: app pass cannot be empty".Root cause
resolvePass(client/webserver/api.go:2339) checks for a password intwo places:
appPW/passfield).getCachedPasswordUsingRequest).The cookies are set during login (
actuallyLogin, line 1596-1602) withSameSite=Strict. GeckoView on Android, connecting via a.onionaddress, may not persist or send these cookies on subsequent requests.
Affected endpoints
The following frontend calls send no password field in the request
body, relying entirely on the cookie cache. All of these will fail from
the companion app:
/api/postbondforms.ts:837/api/discoveracctforms.ts:1732/api/openwalletdexsettings.ts:207,markets.ts:2263,wallets.ts:2260/api/tradeasyncmarkets.ts:2819/api/accelerateorderforms.ts:1481/api/exportaccountdexsettings.ts:300/api/importaccountsettings.ts:380/api/toggleaccountstatusdexsettings.ts:325/api/configuremixerwallets.ts:1756/api/startmarketmakingbotmmutil.ts:128/api/redeemprepaidbondforms.ts:1166/api/redeemgamecodesettings.ts:523Not affected
These endpoints receive the password from the frontend form (e.g. during
initial setup or explicit password prompts):
/api/login- password entered on login form/api/newwallet(frominit.ts) - password passed during setup/api/adddex(frominit.ts) - password passed during setupPossible fixes
Server-side: For companion app (onion) requests, look up the
cached password by companion token instead of by cookie. The server
already knows which companion token is paired and could maintain a
password cache keyed by that token.
Frontend: Ensure the password cookies are included in all
postJSONrequests from GeckoView by adjusting cookie settings(e.g.
SameSite=Nonefor onion requests, or usingcredentials: includein fetch calls).GeckoView config: Investigate whether GeckoView's cookie storage
or privacy settings are stripping cookies on
.oniondomains.