From 08597e54c5fcdce65b983b3ef5618294373044ce Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Fri, 25 Feb 2022 16:20:55 -0800 Subject: [PATCH] AllFlowsTest - Add case `testIgnoredHeaderAuthorization()` --- .../tests/phpunit/Civi/Authx/AllFlowsTest.php | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/ext/authx/tests/phpunit/Civi/Authx/AllFlowsTest.php b/ext/authx/tests/phpunit/Civi/Authx/AllFlowsTest.php index 829519037f..1c374fc05e 100644 --- a/ext/authx/tests/phpunit/Civi/Authx/AllFlowsTest.php +++ b/ext/authx/tests/phpunit/Civi/Authx/AllFlowsTest.php @@ -365,6 +365,59 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf $this->assertMyContact($this->getDemoCID(), $this->getDemoUID(), 'api_key', 'login', $response); } + /** + * Suppose a deployment has two layers of authorization: + * + * (1) a generic/site-wide HTTP restriction (perhaps enforced by a reverse proxy) + * (2) anything/everything else (CMS/login-form/parameter/X-Civi-Auth stuff). + * + * Layer (1) has an `Authorization:` header that should be ignored by `authx`. + * + * This test submits both layer (1) and layer (2) credentials and ensures that authx respects + * the layer (2). + */ + public function testIgnoredHeaderAuthorization() { + // We may submit some other credential - it will be used. + $flowType = 'param'; + $credType = 'api_key'; + + \Civi::settings()->set("authx_header_cred", []); + \Civi::settings()->set("authx_{$flowType}_cred", [$credType]); + + $http = $this->createGuzzle(['http_errors' => FALSE]); + + // We submit both the irrelevant `Authorization:` and the relevant `?_authx=...` (DemoCID). + $request = $this->applyAuth($this->requestMyContact(), 'api_key', 'header', $this->getLebowskiCID()); + $request = $this->applyAuth($request, $credType, $flowType, $this->getDemoCID()); + // $request = $request->withAddedHeader('Authorization', $irrelevantAuthorization); + $response = $http->send($request); + $this->assertMyContact($this->getDemoCID(), $this->getDemoUID(), $credType, $flowType, $response); + if (!in_array('sendsExcessCookies', $this->quirks)) { + $this->assertNoCookies($response); + } + } + + /** + * Similar to testIgnoredHeaderAuthorization(), but the Civi/CMS user is anonymous. + */ + public function testIgnoredHeaderAuthorization_anon() { + $http = $this->createGuzzle(['http_errors' => FALSE]); + + /** @var \Psr\Http\Message\RequestInterface $request */ + + // Variant 1: The `Authorization:` header is ignored (even if the content is totally fake/inauthentic). + \Civi::settings()->set("authx_header_cred", []); + $request = $this->requestMyContact()->withAddedHeader('Authorization', 'Basic ' . base64_encode("not:real")); + $response = $http->send($request); + $this->assertAnonymousContact($response); + + // Variant 2: The `Authorization:` header is ignored (even if the content is sorta-real-ish for LebowskiCID). + \Civi::settings()->set("authx_header_cred", []); + $request = $this->applyAuth($this->requestMyContact(), 'api_key', 'header', $this->getLebowskiCID()); + $response = $http->send($request); + $this->assertAnonymousContact($response); + } + /** * This consumer intends to make stateless requests with a handful of different identities, * but their browser happens to be cookie-enabled. Ensure that identities do not leak between requests. -- 2.25.1