* SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * See the LICENSE file in the project root for the full license text. */ declare(strict_types=1); namespace App\Tests\Auth; use App\Auth\OidcClient; use App\Tests\TestCase; /** * Pins the OIDC env-driven gating: `isConfigured()` is true only when every * ENTRA_* + APP_BASE_URL var is set AND `OIDC_ENABLED` isn't explicitly false. * The `OIDC_ENABLED=false` path is the dev/testing kill-switch that lets * operators run on the LOCAL_ADMIN_* fallback alone without unsetting the * Entra creds in .env. */ final class OidcClientTest extends TestCase { /** @var array */ private array $envBackup = []; /** @var string[] */ private array $envKeys = [ 'ENTRA_TENANT_ID', 'ENTRA_CLIENT_ID', 'ENTRA_CLIENT_SECRET', 'APP_BASE_URL', 'OIDC_ENABLED', ]; protected function setUp(): void { parent::setUp(); foreach ($this->envKeys as $k) { $this->envBackup[$k] = getenv($k); putenv($k); } } protected function tearDown(): void { foreach ($this->envKeys as $k) { $prev = $this->envBackup[$k] ?? false; if ($prev === false) { putenv($k); } else { putenv("{$k}={$prev}"); } } parent::tearDown(); } private function setEntraVars(): void { putenv('ENTRA_TENANT_ID=tenant-guid'); putenv('ENTRA_CLIENT_ID=client-guid'); putenv('ENTRA_CLIENT_SECRET=secret'); putenv('APP_BASE_URL=https://example.com'); } public function testNotConfiguredWithoutEntraVars(): void { self::assertFalse(OidcClient::isConfigured()); self::assertFalse(OidcClient::isExplicitlyDisabled()); } public function testConfiguredWhenAllEntraVarsSet(): void { $this->setEntraVars(); self::assertTrue(OidcClient::isConfigured()); self::assertFalse(OidcClient::isExplicitlyDisabled()); } public function testConfiguredStaysTrueWhenFlagBlankOrUnset(): void { $this->setEntraVars(); // Unset (default of putenv with no =). putenv('OIDC_ENABLED'); self::assertTrue(OidcClient::isConfigured()); // Explicit blank. putenv('OIDC_ENABLED='); self::assertTrue(OidcClient::isConfigured()); self::assertFalse(OidcClient::isExplicitlyDisabled()); } public function testConfiguredStaysTrueWhenFlagAnyTruthyValue(): void { $this->setEntraVars(); foreach (['true', '1', 'yes', 'on', 'TRUE', 'enabled', 'whatever'] as $v) { putenv("OIDC_ENABLED={$v}"); self::assertTrue( OidcClient::isConfigured(), "isConfigured() should be true with OIDC_ENABLED={$v}", ); self::assertFalse( OidcClient::isExplicitlyDisabled(), "isExplicitlyDisabled() should be false with OIDC_ENABLED={$v}", ); } } public function testFalseyFlagDisablesOidcEvenWithEntraVarsSet(): void { $this->setEntraVars(); foreach (['false', '0', 'no', 'off', 'FALSE', 'No', ' off '] as $v) { putenv("OIDC_ENABLED={$v}"); self::assertFalse( OidcClient::isConfigured(), "isConfigured() should be false with OIDC_ENABLED={$v}", ); self::assertTrue( OidcClient::isExplicitlyDisabled(), "isExplicitlyDisabled() should be true with OIDC_ENABLED={$v}", ); } } public function testFalseyFlagWithoutEntraVarsStillReportsDisabled(): void { // No ENTRA_*. Flag set false. isConfigured stays false (already was); // isExplicitlyDisabled tells the operator-facing page which message // to show ("disabled" vs. "not configured"). putenv('OIDC_ENABLED=false'); self::assertFalse(OidcClient::isConfigured()); self::assertTrue(OidcClient::isExplicitlyDisabled()); } }