Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
Authenticate
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
2 / 2
4
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
 process
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray\Api;
6
7use Celema\Core\Exception\HttpUnauthorized;
8use Cosray\Users;
9use Override;
10use Psr\Http\Message\ResponseInterface as Response;
11use Psr\Http\Message\ServerRequestInterface as Request;
12use Psr\Http\Server\MiddlewareInterface as Middleware;
13use Psr\Http\Server\RequestHandlerInterface as Handler;
14
15/**
16 * The user a bearer token acts as, as the `user` request attribute; null
17 * without a token. A token that does not authenticate is refused rather than
18 * treated as anonymous, so a client learns that its token stopped working.
19 */
20final class Authenticate implements Middleware
21{
22    public function __construct(
23        private readonly Users $users,
24    ) {}
25
26    #[Override]
27    public function process(Request $request, Handler $handler): Response
28    {
29        $header = trim($request->getHeaderLine('Authorization'));
30
31        if ($header === '') {
32            return $handler->handle($request->withAttribute('user', null));
33        }
34
35        if (preg_match('/^Bearer\s+(\S+)$/i', $header, $matches) !== 1) {
36            throw new HttpUnauthorized($request, payload: [
37                'message' => 'Send the token as `Authorization: Bearer <token>`.',
38            ]);
39        }
40
41        $user = $this->users->byAuthToken($matches[1])
42            ?? throw new HttpUnauthorized($request, payload: [
43                'message' => 'The token is unknown, revoked or expired.',
44            ]);
45
46        return $handler->handle($request->withAttribute('user', $user));
47    }
48}