• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aphiria / app / 16254939635

14 Jul 2025 12:11AM UTC coverage: 82.303% (-0.05%) from 82.353%
16254939635

Pull #52

github

web-flow
Merge 6744005d0 into 883e6ad8e
Pull Request #52: Re-enabled linter

42 of 50 new or added lines in 9 files covered. (84.0%)

293 of 356 relevant lines covered (82.3%)

9.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

23.53
/src/Auth/Schemes/CookieAuthenticationHandler.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace App\Auth\Schemes;
6

7
use Aphiria\Authentication\AuthenticationResult;
8
use Aphiria\Authentication\AuthenticationScheme;
9
use Aphiria\Authentication\Schemes\CookieAuthenticationHandler as BaseCookieAuthenticationHandler;
10
use Aphiria\Authentication\Schemes\CookieAuthenticationOptions;
11
use Aphiria\Net\Http\IRequest;
12
use Aphiria\Net\Http\IResponse;
13
use Aphiria\Security\IPrincipal;
14
use Aphiria\Security\PrincipalBuilder;
15
use App\Auth\InvalidCredentialsException;
16
use App\Auth\ITokenService;
17
use App\Users\IUserService;
18
use App\Users\UserNotFoundException;
19
use JsonException;
20

21
/**
22
 * Defines a cookie authentication scheme handler
23
 */
24
final class CookieAuthenticationHandler extends BaseCookieAuthenticationHandler
25
{
26
    /** @var int The default cookie TTL in case one is not set in the cookie options */
27
    private const int DEFAULT_COOKIE_TTL_SECONDS = 3600;
28

29
    /**
30
     * @param ITokenService $tokens The token service to create/retrieve tokens from
31
     * @param IUserService $users The user service to retrieve users from
32
     */
33
    public function __construct(
34
        private readonly ITokenService $tokens,
35
        private readonly IUserService $users,
36
    ) {
37
        parent::__construct();
19✔
38
    }
39

40
    /**
41
     * @inheritdoc
42
     * @param AuthenticationScheme<CookieAuthenticationOptions> $scheme The scheme
43
     * @throws InvalidCredentialsException Thrown if there was an error decoding the cookie value
44
     */
45
    public function logOut(IRequest $request, IResponse $response, AuthenticationScheme $scheme): void
46
    {
47
        $cookieValue = $this->getCookieValueFromRequest($request, $scheme);
2✔
48

49
        if ($cookieValue !== null) {
2✔
50
            try {
51
                /** @var array{userId: int, token: string} $decodedCookieValue */
52
                $decodedCookieValue = \json_decode(\base64_decode($cookieValue), true, 512, JSON_THROW_ON_ERROR);
×
53
            } catch (JsonException $ex) {
×
54
                throw new InvalidCredentialsException('Cookie contained invalid JSON', 0, $ex);
×
55
            }
56

NEW
57
            $userId = isset($decodedCookieValue['userId']) ? (int) $decodedCookieValue['userId'] : null;
×
58
            $token = $decodedCookieValue['token'] ?? null;
×
59

60
            if ($userId !== null && $token !== null) {
×
61
                $this->tokens->expireToken($userId, $token);
×
62
            }
63
        }
64

65
        parent::logOut($request, $response, $scheme);
2✔
66
    }
67

68
    /**
69
     * @inheritdoc
70
     * @param AuthenticationScheme<CookieAuthenticationOptions> $scheme The scheme
71
     * @throws UserNotFoundException Thrown if no user was found with the retrieved user ID
72
     */
73
    protected function createAuthenticationResultFromCookie(string $cookieValue, IRequest $request, AuthenticationScheme $scheme): AuthenticationResult
74
    {
75
        try {
76
            /** @var array{userId: int, token: string} $decodedCookieValue */
77
            $decodedCookieValue = \json_decode(\base64_decode($cookieValue), true, 512, JSON_THROW_ON_ERROR);
×
78
        } catch (JsonException) {
×
79
            return AuthenticationResult::fail('Token format is invalid', $scheme->name);
×
80
        }
81

82
        if (!isset($decodedCookieValue['userId'], $decodedCookieValue['token'])) {
×
83
            return AuthenticationResult::fail('Token format is invalid', $scheme->name);
×
84
        }
85

NEW
86
        $userId = (int) $decodedCookieValue['userId'];
×
NEW
87
        $token = (string) $decodedCookieValue['token'];
×
88

89
        if (!$this->tokens->validateToken($userId, $token)) {
×
90
            return AuthenticationResult::fail('Invalid token', $scheme->name);
×
91
        }
92

93
        $user = $this->users->getUserById($userId);
×
94

95
        return AuthenticationResult::pass(
×
96
            new PrincipalBuilder($scheme->options->claimsIssuer ?? $scheme->name)
×
97
                ->withNameIdentifier($user->id)
×
98
                ->withEmail($user->email)
×
99
                ->withRoles($user->roles)
×
100
                ->withAuthenticationSchemeName($scheme->name)
×
101
                ->build(),
×
NEW
102
            $scheme->name,
×
103
        );
×
104
    }
105

106
    /**
107
     * @inheritdoc
108
     * @param AuthenticationScheme<CookieAuthenticationOptions> $scheme The scheme
109
     * @throws JsonException Thrown if there was an error encoding the JSON (very unlikely)
110
     */
111
    protected function createCookieValueForUser(IPrincipal $user, AuthenticationScheme $scheme): string|int|float
112
    {
113
        $cookieTtlSeconds = $scheme->options->cookieMaxAge ?? self::DEFAULT_COOKIE_TTL_SECONDS;
2✔
114
        $userId = (int) $user->primaryIdentity?->nameIdentifier;
2✔
115
        $token = $this->tokens->createToken($userId, $cookieTtlSeconds);
2✔
116

117
        return \base64_encode(\json_encode(['userId' => $userId, 'token' => $token], JSON_THROW_ON_ERROR));
2✔
118
    }
119
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc