| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- <?php
- declare(strict_types=1);
- namespace App\Tests\Integration\Auth;
- use App\Auth\OidcAuthenticator;
- use App\Auth\OidcClaims;
- use App\Auth\OidcException;
- use App\Tests\Integration\Support\AppTestCase;
- /**
- * OIDC flow tested with a stub `OidcAuthenticator`. Real Entra
- * authentication is verified manually; this test guards against
- * regressions in the controller's success/no-access/error branches.
- */
- final class OidcFlowTest extends AppTestCase
- {
- protected function setUp(): void
- {
- $this->bootApp(['oidc_enabled' => true]);
- }
- public function testCallbackSuccessSetsSessionAndRedirectsToMe(): void
- {
- $this->bindOidcAuthenticator(new class () implements OidcAuthenticator {
- public function authenticate(): OidcClaims
- {
- return new OidcClaims(
- subject: 'sub-1',
- email: 'alice@example.com',
- displayName: 'Alice',
- groups: ['group-admin'],
- );
- }
- });
- $this->enqueueApiResponse(200, [
- 'user_id' => 99, 'role' => 'admin', 'email' => 'alice@example.com',
- 'display_name' => 'Alice', 'is_local' => false,
- ]);
- $response = $this->request('GET', '/oidc/callback');
- self::assertSame(302, $response->getStatusCode());
- self::assertSame('/app/me', $response->getHeaderLine('Location'));
- self::assertSame(99, $_SESSION['_user']['user_id'] ?? null);
- self::assertSame('admin', $_SESSION['_user']['role']);
- }
- public function testNoneRoleRedirectsToNoAccess(): void
- {
- $this->bindOidcAuthenticator(new class () implements OidcAuthenticator {
- public function authenticate(): OidcClaims
- {
- return new OidcClaims('sub-x', 'x@x', 'X', []);
- }
- });
- $this->enqueueApiResponse(200, [
- 'user_id' => 0, 'role' => 'none', 'email' => 'x@x', 'display_name' => 'X', 'is_local' => false,
- ]);
- $response = $this->request('GET', '/oidc/callback');
- self::assertSame(302, $response->getStatusCode());
- self::assertSame('/no-access', $response->getHeaderLine('Location'));
- self::assertArrayNotHasKey('_user', $_SESSION);
- }
- public function testHandshakeFailureRedirectsToLogin(): void
- {
- $this->bindOidcAuthenticator(new class () implements OidcAuthenticator {
- public function authenticate(): OidcClaims
- {
- throw new OidcException('state mismatch');
- }
- });
- $response = $this->request('GET', '/oidc/callback');
- self::assertSame(302, $response->getStatusCode());
- self::assertSame('/login', $response->getHeaderLine('Location'));
- $flash = $_SESSION['_flash'] ?? [];
- self::assertNotEmpty($flash);
- self::assertSame('error', $flash[0]['type']);
- }
- public function testApiUnreachableDuringUpsertFlashesAndRedirects(): void
- {
- $this->bindOidcAuthenticator(new class () implements OidcAuthenticator {
- public function authenticate(): OidcClaims
- {
- return new OidcClaims('sub-1', null, 'Alice', []);
- }
- });
- $this->enqueueApiException(new \GuzzleHttp\Exception\ConnectException(
- 'down',
- new \GuzzleHttp\Psr7\Request('POST', '/'),
- ));
- $this->enqueueApiException(new \GuzzleHttp\Exception\ConnectException(
- 'down',
- new \GuzzleHttp\Psr7\Request('POST', '/'),
- ));
- $response = $this->request('GET', '/oidc/callback');
- self::assertSame(302, $response->getStatusCode());
- self::assertSame('/login', $response->getHeaderLine('Location'));
- }
- }
|