From d5d45c50768f7e75cfea7ce052255d4dd915c852 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 26 Mar 2024 18:59:56 +1300 Subject: [PATCH 1/7] Fix not hiding tokens for clients via realtime --- app/controllers/api/account.php | 78 ++++++++++++--------------------- 1 file changed, 28 insertions(+), 50 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 89ccb1e30a..7481c6bb05 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1845,6 +1845,9 @@ App::post('/v1/account/tokens/magic-url') 'team' => '', ]; + // Hide secret for clients + $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : ''); + $queueForMails ->setSubject($subject) ->setBody($body) @@ -1853,23 +1856,16 @@ App::post('/v1/account/tokens/magic-url') ->trigger(); $queueForEvents->setPayload( - $response->output( - $token->setAttribute('secret', $tokenSecret), - Response::MODEL_TOKEN - ) + $response->output($token, Response::MODEL_TOKEN) ); - // Hide secret for clients - $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : ''); - if (!empty($phrase)) { $token->setAttribute('phrase', $phrase); } $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($token, Response::MODEL_TOKEN) - ; + ->dynamic($token, Response::MODEL_TOKEN); }); App::post('/v1/account/tokens/email') @@ -2074,6 +2070,9 @@ App::post('/v1/account/tokens/email') 'team' => '', ]; + // Hide secret for clients + $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : ''); + $queueForMails ->setSubject($subject) ->setBody($body) @@ -2082,23 +2081,16 @@ App::post('/v1/account/tokens/email') ->trigger(); $queueForEvents->setPayload( - $response->output( - $token->setAttribute('secret', $tokenSecret), - Response::MODEL_TOKEN - ) + $response->output($token, Response::MODEL_TOKEN) ); - // Hide secret for clients - $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : ''); - if (!empty($phrase)) { $token->setAttribute('phrase', $phrase); } $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($token, Response::MODEL_TOKEN) - ; + ->dynamic($token, Response::MODEL_TOKEN); }); App::put('/v1/account/sessions/magic-url') @@ -2309,6 +2301,9 @@ App::post('/v1/account/tokens/phone') ], ]); + // Hide secret for clients + $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? Auth::encodeSession($user->getId(), $secret) : ''); + $queueForMessaging ->setType(MESSAGE_SEND_TYPE_INTERNAL) ->setMessage($messageDoc) @@ -2316,19 +2311,12 @@ App::post('/v1/account/tokens/phone') ->setProviderType(MESSAGE_TYPE_SMS); $queueForEvents->setPayload( - $response->output( - $token->setAttribute('secret', $secret), - Response::MODEL_TOKEN - ) + $response->output($token, Response::MODEL_TOKEN) ); - // Hide secret for clients - $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? Auth::encodeSession($user->getId(), $secret) : ''); - $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($token, Response::MODEL_TOKEN) - ; + ->dynamic($token, Response::MODEL_TOKEN); }); App::post('/v1/account/jwt') @@ -2968,6 +2956,9 @@ App::post('/v1/account/recovery') 'team' => '' ]; + // Hide secret for clients + $recovery->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); + $queueForMails ->setRecipient($profile->getAttribute('email', '')) ->setName($profile->getAttribute('name', '')) @@ -2980,14 +2971,7 @@ App::post('/v1/account/recovery') ->setParam('userId', $profile->getId()) ->setParam('tokenId', $recovery->getId()) ->setUser($profile) - ->setPayload($response->output( - $recovery->setAttribute('secret', $secret), - Response::MODEL_TOKEN - )) - ; - - // Hide secret for clients - $recovery->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); + ->setPayload($response->output($recovery, Response::MODEL_TOKEN)); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -3158,6 +3142,7 @@ App::post('/v1/account/verification') ->setParam('{{footer}}', $locale->getText("emails.verification.footer")) ->setParam('{{thanks}}', $locale->getText("emails.verification.thanks")) ->setParam('{{signature}}', $locale->getText("emails.verification.signature")); + $body = $message->render(); $smtp = $project->getAttribute('smtp', []); @@ -3216,6 +3201,9 @@ App::post('/v1/account/verification') 'team' => '', ]; + // Hide secret for clients + $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $verificationSecret : ''); + $queueForMails ->setSubject($subject) ->setBody($body) @@ -3227,13 +3215,7 @@ App::post('/v1/account/verification') $queueForEvents ->setParam('userId', $user->getId()) ->setParam('tokenId', $verification->getId()) - ->setPayload($response->output( - $verification->setAttribute('secret', $verificationSecret), - Response::MODEL_TOKEN - )); - - // Hide secret for clients - $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $verificationSecret : ''); + ->setPayload($response->output($verification, Response::MODEL_TOKEN)); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -3389,6 +3371,9 @@ App::post('/v1/account/verification/phone') ], ]); + // Hide secret for clients + $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); + $queueForMessaging ->setType(MESSAGE_SEND_TYPE_INTERNAL) ->setMessage($messageDoc) @@ -3398,14 +3383,7 @@ App::post('/v1/account/verification/phone') $queueForEvents ->setParam('userId', $user->getId()) ->setParam('tokenId', $verification->getId()) - ->setPayload($response->output( - $verification->setAttribute('secret', $secret), - Response::MODEL_TOKEN - )) - ; - - // Hide secret for clients - $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); + ->setPayload($response->output($verification, Response::MODEL_TOKEN)); $response ->setStatusCode(Response::STATUS_CODE_CREATED) From e224ca440b1f5a8bdc73a2e3494bcc2f62c0486e Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 3 Apr 2024 16:36:21 +1300 Subject: [PATCH 2/7] Allow setting event parameters as sensitive --- app/controllers/shared/api.php | 2 +- src/Appwrite/Event/Event.php | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index ad9ed97b63..2444813b40 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -590,7 +590,7 @@ App::shutdown() Realtime::send( projectId: $target['projectId'] ?? $project->getId(), - payload: $queueForEvents->getPayload(), + payload: $queueForEvents->getRealtimePayload(), events: $allEvents, channels: $target['channels'], roles: $target['roles'], diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index fa9ddf1315..f85195b154 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -52,6 +52,7 @@ class Event protected string $class = ''; protected string $event = ''; protected array $params = []; + protected array $sensitive = []; protected array $payload = []; protected array $context = []; protected ?Document $project = null; @@ -161,12 +162,17 @@ class Event * Set payload for this event. * * @param array $payload + * @param array $sensitive * @return self */ - public function setPayload(array $payload): self + public function setPayload(array $payload, array $sensitive = []): self { $this->payload = $payload; + foreach ($sensitive as $key) { + $this->sensitive[$key] = true; + } + return $this; } @@ -180,6 +186,19 @@ class Event return $this->payload; } + public function getRealtimePayload(): array + { + $payload = []; + + foreach ($this->payload as $key => $value) { + if (!isset($this->sensitive[$key])) { + $payload[$key] = $value; + } + } + + return $payload; + } + /** * Set context for this event. * @@ -242,6 +261,13 @@ class Event return $this; } + public function setParamSensitive(string $key): self + { + $this->sensitive[$key] = true; + + return $this; + } + /** * Get param of event. * @@ -294,6 +320,7 @@ class Event public function reset(): self { $this->params = []; + $this->sensitive = []; return $this; } From fb408636a4dcd652647d856630a930723a853ccf Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 3 Apr 2024 16:36:53 +1300 Subject: [PATCH 3/7] Set token secrets as sensitive event params --- app/controllers/api/account.php | 64 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 7481c6bb05..d9ece1a464 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1845,9 +1845,6 @@ App::post('/v1/account/tokens/magic-url') 'team' => '', ]; - // Hide secret for clients - $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : ''); - $queueForMails ->setSubject($subject) ->setBody($body) @@ -1855,14 +1852,16 @@ App::post('/v1/account/tokens/magic-url') ->setRecipient($email) ->trigger(); - $queueForEvents->setPayload( - $response->output($token, Response::MODEL_TOKEN) - ); + $queueForEvents + ->setPayload($response->output($token, Response::MODEL_TOKEN), sensitive: ['secret']); if (!empty($phrase)) { $token->setAttribute('phrase', $phrase); } + // Hide secret for clients + $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : ''); + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($token, Response::MODEL_TOKEN); @@ -2070,9 +2069,6 @@ App::post('/v1/account/tokens/email') 'team' => '', ]; - // Hide secret for clients - $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : ''); - $queueForMails ->setSubject($subject) ->setBody($body) @@ -2080,14 +2076,16 @@ App::post('/v1/account/tokens/email') ->setRecipient($email) ->trigger(); - $queueForEvents->setPayload( - $response->output($token, Response::MODEL_TOKEN) - ); + $queueForEvents + ->setPayload($response->output($token, Response::MODEL_TOKEN), sensitive: ['secret']); if (!empty($phrase)) { $token->setAttribute('phrase', $phrase); } + // Hide secret for clients + $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : ''); + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($token, Response::MODEL_TOKEN); @@ -2301,18 +2299,17 @@ App::post('/v1/account/tokens/phone') ], ]); - // Hide secret for clients - $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? Auth::encodeSession($user->getId(), $secret) : ''); - $queueForMessaging ->setType(MESSAGE_SEND_TYPE_INTERNAL) ->setMessage($messageDoc) ->setRecipients([$phone]) ->setProviderType(MESSAGE_TYPE_SMS); - $queueForEvents->setPayload( - $response->output($token, Response::MODEL_TOKEN) - ); + $queueForEvents + ->setPayload($response->output($token, Response::MODEL_TOKEN), sensitive: ['secret']); + + // Hide secret for clients + $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? Auth::encodeSession($user->getId(), $secret) : ''); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -2956,9 +2953,6 @@ App::post('/v1/account/recovery') 'team' => '' ]; - // Hide secret for clients - $recovery->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); - $queueForMails ->setRecipient($profile->getAttribute('email', '')) ->setName($profile->getAttribute('name', '')) @@ -2971,7 +2965,10 @@ App::post('/v1/account/recovery') ->setParam('userId', $profile->getId()) ->setParam('tokenId', $recovery->getId()) ->setUser($profile) - ->setPayload($response->output($recovery, Response::MODEL_TOKEN)); + ->setPayload($response->output($recovery, Response::MODEL_TOKEN), sensitive: ['secret']); + + // Hide secret for clients + $recovery->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -3201,9 +3198,6 @@ App::post('/v1/account/verification') 'team' => '', ]; - // Hide secret for clients - $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $verificationSecret : ''); - $queueForMails ->setSubject($subject) ->setBody($body) @@ -3215,7 +3209,10 @@ App::post('/v1/account/verification') $queueForEvents ->setParam('userId', $user->getId()) ->setParam('tokenId', $verification->getId()) - ->setPayload($response->output($verification, Response::MODEL_TOKEN)); + ->setPayload($response->output($verification, Response::MODEL_TOKEN), sensitive: ['secret']); + + // Hide secret for clients + $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $verificationSecret : ''); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -3265,7 +3262,7 @@ App::put('/v1/account/verification') $user->setAttributes($profile->getArrayCopy()); - $verificationDocument = $dbForProject->getDocument('tokens', $verifiedToken->getId()); + $verification = $dbForProject->getDocument('tokens', $verifiedToken->getId()); /** * We act like we're updating and validating @@ -3276,10 +3273,9 @@ App::put('/v1/account/verification') $queueForEvents ->setParam('userId', $userId) - ->setParam('tokenId', $verificationDocument->getId()) - ; + ->setParam('tokenId', $verification->getId()); - $response->dynamic($verificationDocument, Response::MODEL_TOKEN); + $response->dynamic($verification, Response::MODEL_TOKEN); }); App::post('/v1/account/verification/phone') @@ -3371,9 +3367,6 @@ App::post('/v1/account/verification/phone') ], ]); - // Hide secret for clients - $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); - $queueForMessaging ->setType(MESSAGE_SEND_TYPE_INTERNAL) ->setMessage($messageDoc) @@ -3383,7 +3376,10 @@ App::post('/v1/account/verification/phone') $queueForEvents ->setParam('userId', $user->getId()) ->setParam('tokenId', $verification->getId()) - ->setPayload($response->output($verification, Response::MODEL_TOKEN)); + ->setPayload($response->output($verification, Response::MODEL_TOKEN), sensitive: ['secret']); + + // Hide secret for clients + $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); $response ->setStatusCode(Response::STATUS_CODE_CREATED) From 6f18303fcc027b52ae1729f795f8f3e473f0818b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 3 Apr 2024 16:37:58 +1300 Subject: [PATCH 4/7] Test that secret is not included in realtime payload --- tests/e2e/Services/Realtime/RealtimeCustomClientTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index 9b73566bda..d1098cb7e2 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -290,7 +290,6 @@ class RealtimeCustomClientTest extends Scope $this->assertEquals($name, $response['data']['payload']['name']); - /** * Test Account Password Event */ @@ -376,6 +375,7 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($response['data']); $this->assertCount(2, $response['data']['channels']); $this->assertArrayHasKey('timestamp', $response['data']); + $this->assertArrayNotHasKey('secret', $response['data']); $this->assertContains('account', $response['data']['channels']); $this->assertContains('account.' . $userId, $response['data']['channels']); $this->assertContains("users.{$userId}.verification.{$verificationId}.create", $response['data']['events']); From 93f50e1e0e46ba6dc5a887f28a39576a36476bb1 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 22 May 2024 12:51:27 +1200 Subject: [PATCH 5/7] Lint --- .../Webhooks/WebhooksCustomClientTest.php | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php index f331db905b..a170492551 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php @@ -44,7 +44,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -120,7 +120,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -174,7 +174,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -263,7 +263,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -349,7 +349,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -440,7 +440,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); @@ -494,7 +494,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -549,7 +549,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -605,7 +605,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -661,7 +661,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -719,7 +719,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -774,7 +774,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -833,7 +833,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); @@ -891,7 +891,7 @@ class WebhooksCustomClientTest extends Scope $webhook = $this->getLastRequest(); $signatureKey = $this->getProject()['signatureKey']; $payload = json_encode($webhook['data']); - $url = $webhook['url']; + $url = $webhook['url']; $signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true)); $this->assertEquals($webhook['method'], 'POST'); From f03281a474b5bde57cc507e7e6641fba3af4e86b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 22 May 2024 13:42:34 +1200 Subject: [PATCH 6/7] Fix project tests --- .../Services/Projects/ProjectsConsoleClientTest.php | 2 +- .../Services/Projects/ProjectsCustomClientTest.php | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 tests/e2e/Services/Projects/ProjectsCustomClientTest.php diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 7be668e17e..1357628451 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -1252,7 +1252,7 @@ class ProjectsConsoleClientTest extends Scope 'name' => $name, ]); - $this->assertEquals($response['headers']['status-code'], 501); + $this->assertEquals(400, $response['headers']['status-code']); /** * Test for FAILURE diff --git a/tests/e2e/Services/Projects/ProjectsCustomClientTest.php b/tests/e2e/Services/Projects/ProjectsCustomClientTest.php deleted file mode 100644 index b8d43fc544..0000000000 --- a/tests/e2e/Services/Projects/ProjectsCustomClientTest.php +++ /dev/null @@ -1,13 +0,0 @@ - Date: Wed, 22 May 2024 14:11:06 +1200 Subject: [PATCH 7/7] Fix returning hashed secrets --- app/controllers/api/account.php | 46 ++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index f60635dea7..0ad0088d80 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1856,16 +1856,21 @@ App::post('/v1/account/tokens/magic-url') ->setRecipient($email) ->trigger(); + // Set to unhashed secret for events and server responses + $token->setAttribute('secret', $tokenSecret); + $queueForEvents ->setPayload($response->output($token, Response::MODEL_TOKEN), sensitive: ['secret']); + // Hide secret for clients + if (!$isPrivilegedUser && !$isAppUser) { + $token->setAttribute('secret', ''); + } + if (!empty($phrase)) { $token->setAttribute('phrase', $phrase); } - // Hide secret for clients - $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : ''); - $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($token, Response::MODEL_TOKEN); @@ -2080,16 +2085,21 @@ App::post('/v1/account/tokens/email') ->setRecipient($email) ->trigger(); + // Set to unhashed secret for events and server responses + $token->setAttribute('secret', $tokenSecret); + $queueForEvents ->setPayload($response->output($token, Response::MODEL_TOKEN), sensitive: ['secret']); + // Hide secret for clients + if (!$isPrivilegedUser && !$isAppUser) { + $token->setAttribute('secret', ''); + } + if (!empty($phrase)) { $token->setAttribute('phrase', $phrase); } - // Hide secret for clients - $token->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $tokenSecret : ''); - $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($token, Response::MODEL_TOKEN); @@ -2309,6 +2319,9 @@ App::post('/v1/account/tokens/phone') ->setRecipients([$phone]) ->setProviderType(MESSAGE_TYPE_SMS); + // Set to unhashed secret for events and server responses + $token->setAttribute('secret', $secret); + $queueForEvents ->setPayload($response->output($token, Response::MODEL_TOKEN), sensitive: ['secret']); @@ -2965,6 +2978,9 @@ App::post('/v1/account/recovery') ->setSubject($subject) ->trigger(); + // Set to unhashed secret for events and server responses + $recovery->setAttribute('secret', $secret); + $queueForEvents ->setParam('userId', $profile->getId()) ->setParam('tokenId', $recovery->getId()) @@ -2972,7 +2988,9 @@ App::post('/v1/account/recovery') ->setPayload($response->output($recovery, Response::MODEL_TOKEN), sensitive: ['secret']); // Hide secret for clients - $recovery->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); + if (!$isPrivilegedUser && !$isAppUser) { + $recovery->setAttribute('secret', ''); + } $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -3210,13 +3228,18 @@ App::post('/v1/account/verification') ->setName($user->getAttribute('name') ?? '') ->trigger(); + // Set to unhashed secret for events and server responses + $verification->setAttribute('secret', $verificationSecret); + $queueForEvents ->setParam('userId', $user->getId()) ->setParam('tokenId', $verification->getId()) ->setPayload($response->output($verification, Response::MODEL_TOKEN), sensitive: ['secret']); // Hide secret for clients - $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $verificationSecret : ''); + if (!$isPrivilegedUser && !$isAppUser) { + $verification->setAttribute('secret', ''); + } $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -3377,13 +3400,18 @@ App::post('/v1/account/verification/phone') ->setRecipients([$user->getAttribute('phone')]) ->setProviderType(MESSAGE_TYPE_SMS); + // Set to unhashed secret for events and server responses + $verification->setAttribute('secret', $secret); + $queueForEvents ->setParam('userId', $user->getId()) ->setParam('tokenId', $verification->getId()) ->setPayload($response->output($verification, Response::MODEL_TOKEN), sensitive: ['secret']); // Hide secret for clients - $verification->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : ''); + if (!$isPrivilegedUser && !$isAppUser) { + $verification->setAttribute('secret', ''); + } $response ->setStatusCode(Response::STATUS_CODE_CREATED)