From 676d53b18e2057bf5fa75397544aca264260aa34 Mon Sep 17 00:00:00 2001 From: Ujjwaljain16 Date: Tue, 9 Dec 2025 02:18:40 +0530 Subject: [PATCH 1/5] fix: resolve MFA recovery code validation in 1.8.0 Remove strtolower() from recovery code type comparison (line 4945) Remove strtolower() from match statement (line 4967) Add comprehensive test for recovery code challenge validation Fixes issue where recovery codes fail with 'Invalid token' error Fixes #10740 --- app/controllers/api/account.php | 4 +- .../Account/AccountCustomClientTest.php | 112 ++++++++++++++++++ 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 5563fc6a59..c697fe9ec6 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -4942,7 +4942,7 @@ App::put('/v1/account/mfa/challenge') $recoveryCodeChallenge = function (Document $challenge, Document $user, string $otp) use ($dbForProject) { if ( $challenge->isSet('type') && - $challenge->getAttribute('type') === \strtolower(Type::RECOVERY_CODE) + $challenge->getAttribute('type') === Type::RECOVERY_CODE ) { $mfaRecoveryCodes = $user->getAttribute('mfaRecoveryCodes', []); if (in_array($otp, $mfaRecoveryCodes)) { @@ -4964,7 +4964,7 @@ App::put('/v1/account/mfa/challenge') Type::TOTP => Challenge\TOTP::challenge($challenge, $user, $otp), Type::PHONE => Challenge\Phone::challenge($challenge, $user, $otp), Type::EMAIL => Challenge\Email::challenge($challenge, $user, $otp), - \strtolower(Type::RECOVERY_CODE) => $recoveryCodeChallenge($challenge, $user, $otp), + Type::RECOVERY_CODE => $recoveryCodeChallenge($challenge, $user, $otp), default => false }); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 0993f68a58..c93f8ae034 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -3072,4 +3072,116 @@ class AccountCustomClientTest extends Scope $this->assertEquals('test-identifier-updated', $response['body']['identifier']); $this->assertEquals(false, $response['body']['expired']); } + + /** + * @depends testCreateAccount + */ + public function testMFARecoveryCodeChallenge($data): void + { + $email = $data['email'] ?? ''; + $password = $data['password'] ?? ''; + + // Create session first + $session = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'email' => $email, + 'password' => $password, + ]); + + $this->assertEquals(201, $session['headers']['status-code']); + $sessionCookie = $session['cookies']['a_session_' . $this->getProject()['$id']]; + + // Generate recovery codes + $response = $this->client->call(Client::METHOD_POST, '/account/mfa/recovery-codes', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['recoveryCodes']); + $recoveryCodes = $response['body']['recoveryCodes']; + $this->assertGreaterThan(0, count($recoveryCodes)); + + // Create recovery code challenge + $challenge = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'factor' => 'recoveryCode' + ]); + + $this->assertEquals(201, $challenge['headers']['status-code']); + $this->assertNotEmpty($challenge['body']['$id']); + $challengeId = $challenge['body']['$id']; + + // Test SUCCESS: Verify with valid recovery code (this tests the bug fix) + $verification = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'challengeId' => $challengeId, + 'otp' => $recoveryCodes[0] + ]); + + $this->assertEquals(200, $verification['headers']['status-code']); + $this->assertArrayHasKey('factors', $verification['body']); + $this->assertContains('recoveryCode', $verification['body']['factors']); + + // Test that the code was consumed (can't use again) + $challenge2 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'factor' => 'recoveryCode' + ]); + + $this->assertEquals(201, $challenge2['headers']['status-code']); + + $verification2 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'challengeId' => $challenge2['body']['$id'], + 'otp' => $recoveryCodes[0] // Same code should fail + ]); + + $this->assertEquals(401, $verification2['headers']['status-code']); + + // Test FAILURE: Invalid recovery code + $challenge3 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'factor' => 'recoveryCode' + ]); + + $this->assertEquals(201, $challenge3['headers']['status-code']); + + $verification3 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'challengeId' => $challenge3['body']['$id'], + 'otp' => 'invalid-code-123' + ]); + + $this->assertEquals(401, $verification3['headers']['status-code']); + } } From 768d293cf5ab54c4fb8cb728e6d588be064b633d Mon Sep 17 00:00:00 2001 From: Ujjwaljain16 Date: Wed, 10 Dec 2025 01:58:47 +0530 Subject: [PATCH 2/5] reuse session from testCreateAccountSession instead of creating new session remove unnecessary 'origin' headers to match other tests set status code to 201 for MFA challenge creation endpoint --- app/controllers/api/account.php | 4 +- .../Account/AccountCustomClientTest.php | 69 +++++++------------ 2 files changed, 27 insertions(+), 46 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index c697fe9ec6..0350ba39bd 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -4874,7 +4874,9 @@ App::post('/v1/account/mfa/challenge') ->setParam('userId', $user->getId()) ->setParam('challengeId', $challenge->getId()); - $response->dynamic($challenge, Response::MODEL_MFA_CHALLENGE); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($challenge, Response::MODEL_MFA_CHALLENGE); }); App::put('/v1/account/mfa/challenge') diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index c93f8ae034..bac8e9ad72 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -3074,33 +3074,18 @@ class AccountCustomClientTest extends Scope } /** - * @depends testCreateAccount + * @depends testCreateAccountSession */ public function testMFARecoveryCodeChallenge($data): void - { - $email = $data['email'] ?? ''; - $password = $data['password'] ?? ''; - - // Create session first - $session = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ]), [ - 'email' => $email, - 'password' => $password, - ]); - - $this->assertEquals(201, $session['headers']['status-code']); - $sessionCookie = $session['cookies']['a_session_' . $this->getProject()['$id']]; + { + $session = $data['session'] ?? ''; // Generate recovery codes - $response = $this->client->call(Client::METHOD_POST, '/account/mfa/recovery-codes', array_merge([ - 'origin' => 'http://localhost', + $response = $this->client->call(Client::METHOD_POST, '/account/mfa/recovery-codes', [ 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, 'x-appwrite-project' => $this->getProject()['$id'], - ])); + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['recoveryCodes']); @@ -3108,12 +3093,11 @@ class AccountCustomClientTest extends Scope $this->assertGreaterThan(0, count($recoveryCodes)); // Create recovery code challenge - $challenge = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', + $challenge = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', [ 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, 'x-appwrite-project' => $this->getProject()['$id'], - ]), [ + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ], [ 'factor' => 'recoveryCode' ]); @@ -3122,12 +3106,11 @@ class AccountCustomClientTest extends Scope $challengeId = $challenge['body']['$id']; // Test SUCCESS: Verify with valid recovery code (this tests the bug fix) - $verification = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', + $verification = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', [ 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, 'x-appwrite-project' => $this->getProject()['$id'], - ]), [ + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ], [ 'challengeId' => $challengeId, 'otp' => $recoveryCodes[0] ]); @@ -3137,23 +3120,21 @@ class AccountCustomClientTest extends Scope $this->assertContains('recoveryCode', $verification['body']['factors']); // Test that the code was consumed (can't use again) - $challenge2 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', + $challenge2 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', [ 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, 'x-appwrite-project' => $this->getProject()['$id'], - ]), [ + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ], [ 'factor' => 'recoveryCode' ]); $this->assertEquals(201, $challenge2['headers']['status-code']); - $verification2 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', + $verification2 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', [ 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, 'x-appwrite-project' => $this->getProject()['$id'], - ]), [ + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ], [ 'challengeId' => $challenge2['body']['$id'], 'otp' => $recoveryCodes[0] // Same code should fail ]); @@ -3161,23 +3142,21 @@ class AccountCustomClientTest extends Scope $this->assertEquals(401, $verification2['headers']['status-code']); // Test FAILURE: Invalid recovery code - $challenge3 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', + $challenge3 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', [ 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, 'x-appwrite-project' => $this->getProject()['$id'], - ]), [ + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ], [ 'factor' => 'recoveryCode' ]); $this->assertEquals(201, $challenge3['headers']['status-code']); - $verification3 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', + $verification3 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', [ 'content-type' => 'application/json', - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $sessionCookie, 'x-appwrite-project' => $this->getProject()['$id'], - ]), [ + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ], [ 'challengeId' => $challenge3['body']['$id'], 'otp' => 'invalid-code-123' ]); From 0215577bc7162f9b3005edfe3aa6e70b3172abba Mon Sep 17 00:00:00 2001 From: Ujjwaljain16 Date: Wed, 10 Dec 2025 05:37:43 +0530 Subject: [PATCH 3/5] fix: MFA recovery code validation and test status code - Fixed HTTP status code: POST /v1/account/mfa/recovery-codes now returns 201 (CREATED) instead of 200 - Updated testMFARecoveryCodeChallenge to expect 201 status code - Added array_merge with origin header to all API calls in test for proper CORS validation - Removed trailing whitespace for PSR-12 compliance Fixes #10740 --- app/controllers/api/account.php | 4 +- .../Account/AccountCustomClientTest.php | 39 +++++++++++-------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 0350ba39bd..0d2e210ed9 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -4421,7 +4421,9 @@ App::post('/v1/account/mfa/recovery-codes') 'recoveryCodes' => $mfaRecoveryCodes ]); - $response->dynamic($document, Response::MODEL_MFA_RECOVERY_CODES); + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($document, Response::MODEL_MFA_RECOVERY_CODES); }); App::patch('/v1/account/mfa/recovery-codes') diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index bac8e9ad72..d106dc1abf 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -3077,27 +3077,29 @@ class AccountCustomClientTest extends Scope * @depends testCreateAccountSession */ public function testMFARecoveryCodeChallenge($data): void - { + { $session = $data['session'] ?? ''; // Generate recovery codes - $response = $this->client->call(Client::METHOD_POST, '/account/mfa/recovery-codes', [ + $response = $this->client->call(Client::METHOD_POST, '/account/mfa/recovery-codes', array_merge([ + 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]); + ])); - $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['recoveryCodes']); $recoveryCodes = $response['body']['recoveryCodes']; $this->assertGreaterThan(0, count($recoveryCodes)); // Create recovery code challenge - $challenge = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', [ + $challenge = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ], [ + ]), [ 'factor' => 'recoveryCode' ]); @@ -3106,11 +3108,12 @@ class AccountCustomClientTest extends Scope $challengeId = $challenge['body']['$id']; // Test SUCCESS: Verify with valid recovery code (this tests the bug fix) - $verification = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', [ + $verification = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ], [ + ]), [ 'challengeId' => $challengeId, 'otp' => $recoveryCodes[0] ]); @@ -3120,21 +3123,23 @@ class AccountCustomClientTest extends Scope $this->assertContains('recoveryCode', $verification['body']['factors']); // Test that the code was consumed (can't use again) - $challenge2 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', [ + $challenge2 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ], [ + ]), [ 'factor' => 'recoveryCode' ]); $this->assertEquals(201, $challenge2['headers']['status-code']); - $verification2 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', [ + $verification2 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ], [ + ]), [ 'challengeId' => $challenge2['body']['$id'], 'otp' => $recoveryCodes[0] // Same code should fail ]); @@ -3142,21 +3147,23 @@ class AccountCustomClientTest extends Scope $this->assertEquals(401, $verification2['headers']['status-code']); // Test FAILURE: Invalid recovery code - $challenge3 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', [ + $challenge3 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ], [ + ]), [ 'factor' => 'recoveryCode' ]); $this->assertEquals(201, $challenge3['headers']['status-code']); - $verification3 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', [ + $verification3 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ + 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ], [ + ]), [ 'challengeId' => $challenge3['body']['$id'], 'otp' => 'invalid-code-123' ]); From fb3b3ae51eff46c3eac86ca906877a2df720f5a4 Mon Sep 17 00:00:00 2001 From: Ujjwaljain16 Date: Wed, 10 Dec 2025 15:40:40 +0530 Subject: [PATCH 4/5] fix: add missing empty body array parameter to recovery codes API call --- tests/e2e/Services/Account/AccountCustomClientTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index d106dc1abf..12a7e144e0 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -3086,7 +3086,7 @@ class AccountCustomClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ])); + ]), []); $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['recoveryCodes']); From 7fc8c6ae4390c25c9f7bbb37960c86babe0de81b Mon Sep 17 00:00:00 2001 From: Ujjwaljain16 Date: Thu, 11 Dec 2025 01:50:52 +0530 Subject: [PATCH 5/5] Simplify testMFARecoveryCodeChallenge to use existing session --- .../Account/AccountCustomClientTest.php | 37 +++++-------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 12a7e144e0..4564d90e23 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -3073,20 +3073,13 @@ class AccountCustomClientTest extends Scope $this->assertEquals(false, $response['body']['expired']); } - /** - * @depends testCreateAccountSession - */ - public function testMFARecoveryCodeChallenge($data): void + public function testMFARecoveryCodeChallenge(): void { - $session = $data['session'] ?? ''; - - // Generate recovery codes + // Generate recovery codes using existing authenticated session $response = $this->client->call(Client::METHOD_POST, '/account/mfa/recovery-codes', array_merge([ - 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), []); + ], $this->getHeaders()), []); $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['recoveryCodes']); @@ -3095,11 +3088,9 @@ class AccountCustomClientTest extends Scope // Create recovery code challenge $challenge = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), [ + ], $this->getHeaders()), [ 'factor' => 'recoveryCode' ]); @@ -3109,11 +3100,9 @@ class AccountCustomClientTest extends Scope // Test SUCCESS: Verify with valid recovery code (this tests the bug fix) $verification = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), [ + ], $this->getHeaders()), [ 'challengeId' => $challengeId, 'otp' => $recoveryCodes[0] ]); @@ -3124,22 +3113,18 @@ class AccountCustomClientTest extends Scope // Test that the code was consumed (can't use again) $challenge2 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), [ + ], $this->getHeaders()), [ 'factor' => 'recoveryCode' ]); $this->assertEquals(201, $challenge2['headers']['status-code']); $verification2 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), [ + ], $this->getHeaders()), [ 'challengeId' => $challenge2['body']['$id'], 'otp' => $recoveryCodes[0] // Same code should fail ]); @@ -3148,22 +3133,18 @@ class AccountCustomClientTest extends Scope // Test FAILURE: Invalid recovery code $challenge3 = $this->client->call(Client::METHOD_POST, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), [ + ], $this->getHeaders()), [ 'factor' => 'recoveryCode' ]); $this->assertEquals(201, $challenge3['headers']['status-code']); $verification3 = $this->client->call(Client::METHOD_PUT, '/account/mfa/challenge', array_merge([ - 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), [ + ], $this->getHeaders()), [ 'challengeId' => $challenge3['body']['$id'], 'otp' => 'invalid-code-123' ]);