appwrite / appwrite/sdk-for-cli

appwrite login --mfa/--code never creates the MFA challenge (self-hosted TOTP)

Open
#363 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
Go
Stars
100
Forks
45
Avg merge
1d 1h
Merged PRs (30d)
5

Description

### 👟 Reproduction steps

Self-hosted Appwrite 1.9.6, CLI 27.3.0 (Homebrew, darwin/arm64). Console account has TOTP enabled as its **only** MFA factor (`GET /v1/account/mfa/factors` → `{"totp":true,"phone":false,"email":false,"recoveryCode":false}`).

```console
$ appwrite login --endpoint "https://appwrite.example.com/v1" \
--email me@example.com --password '' --mfa totp --code 130705
✗ Error: More factors are required to complete the sign in process.
```

Same result with a fresh code every time, and with `--code` alone or `--mfa` alone.

### 👍 Expected behavior

After `POST /v1/account/sessions/email` returns `user_more_factors_required`, the CLI should create an MFA challenge for the factor given in `--mfa` (`POST /v1/account/mfa/challenge`) and verify it with `--code` (`PUT /v1/account/mfa/challenge`), then store the elevated session.

### 👎 Actual Behavior

The CLI never creates the challenge. `--verbose` shows the request sequence stops right after the email session call:

```
· GET /v1/health/version 200
· GET /v1/account 200
· POST /v1/account/sessions/email 401
```

No `POST /v1/account/mfa/challenge` is ever issued, so `--mfa` / `--code` are effectively ignored and the error from step 1 is surfaced as-is.

Worse, the partial (unelevated) session cookie appears to be written to `~/.appwrite/prefs.json` anyway. Subsequent commands then fail confusingly:

```console
$ appwrite pull all
✗ Error: you are not authenticated. Run `appwrite login` to authenticate and try again
```

Doing the three calls by hand against the same server works fine and produces a usable session:

```bash
curl -c c.txt -X POST "$EP/account/sessions/email" -H "X-Appwrite-Project: console" \
-H 'Content-Type: application/json' -d '{"email":"...","password":"..."}'
CH=$(curl -b c.txt -X POST "$EP/account/mfa/challenge" -H "X-Appwrite-Project: console" \
-H 'Content-Type: application/json' -d '{"factor":"totp"}') # → challengeId
curl -b c.txt -c c.txt -X PUT "$EP/account/mfa/challenge" -H "X-Appwrite-Project: console" \
-H 'Content-Type: application/json' -d '{"challengeId":"'"$ID"'","otp":"123456"}'
```

Writing that cookie into `~/.appwrite/prefs.json` makes the CLI work normally, which confirms the server side is fine and the gap is in the CLI's login flow.

Note: `--mfa` also has a misleading UX — `--mfa 123456` fails with `flag needs an argument` guidance that doesn't hint the value is a *factor name*, not the code.

### 🎲 Appwrite version

Different version (specify in environment)

### 💻 Operating system

MacOS

### 🧱 Your Environment

Appwrite server 1.9.6 (self-hosted, behind HTTPS). appwrite-cli 27.3.0 installed via Homebrew, macOS 15 / arm64.

### 👀 Have you spent some time to check if this issue has been raised before?

- [x] I checked and didn't find similar issue

### 🏢 Have you read the Code of Conduct?

- [x] I have read the [Code of Conduct](https://github.com/appwrite/.github/blob/main/CODE_OF_CONDUCT.md)

Contributor guide

Open the contributing guide

Research direction

Start at the `appwrite login` flow and trace handling of `POST /v1/account/sessions/email` when it returns `user_more_factors_required`, then follow how the session cookie is written to `~/.appwrite/prefs.json`. Reproduce against a self-hosted Appwrite 1.9.6 instance and verify that the MFA challenge and verification requests occur, the elevated session is stored, and `--mfa` help distinguishes factor names from codes.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
authentication, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.