Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
HeaderAuthenticator
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
2 / 2
5
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 authenticate
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3declare(strict_types=1);
4
5namespace LambdaTwelve\OneRecord\Testing;
6
7use LambdaTwelve\OneRecord\Rdf\Iri;
8use LambdaTwelve\OneRecord\Server\Spi\Agent;
9use LambdaTwelve\OneRecord\Server\Spi\Authenticator;
10use Psr\Http\Message\ServerRequestInterface;
11
12/**
13 * A test double that trusts an X-Test-Agent header. Tests of endpoint
14 * behaviour do not need real tokens; JwtAuthenticator has its own tests.
15 *
16 * It is an authentication bypass by design, so it defends against being wired
17 * into a real deployment by mistake: outside the PHP CLI (PHPUnit) it
18 * authenticates nobody unless constructed with $allowOutsideCli, which no
19 * production configuration should ever pass.
20 */
21final class HeaderAuthenticator implements Authenticator
22{
23    public const string HEADER = 'X-Test-Agent';
24
25    private readonly string $sapi;
26
27    /**
28     * @param bool $allowOutsideCli trust the header under a web SAPI too (an in-process test server, never production)
29     * @param ?string $sapi the SAPI to decide on; defaults to PHP_SAPI, injectable for tests of this class
30     */
31    public function __construct(private readonly bool $allowOutsideCli = false, ?string $sapi = null)
32    {
33        $this->sapi = $sapi ?? PHP_SAPI;
34    }
35
36    public function authenticate(ServerRequestInterface $request): ?Agent
37    {
38        if (!$this->allowOutsideCli && !\in_array($this->sapi, ['cli', 'phpdbg'], true)) {
39            return null;
40        }
41        $iri = $request->getHeaderLine(self::HEADER);
42
43        return $iri === '' ? null : new Agent(new Iri($iri), 'https://test.issuer', ['sub' => $iri]);
44    }
45}