Test Setup Failed
Push — main ( 7bb2c5...c5b0e8 )
by Daniel
03:55
created

AuthenticationProvider::authByToken()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 2
nop 3
dl 0
loc 13
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Uxmp\Core\Component\SubSonic;
6
7
use Usox\HyperSonic\Authentication\AuthenticationProviderInterface;
8
use Usox\HyperSonic\Authentication\Exception\AuthenticationFailedException;
9
use Uxmp\Core\Component\Authentication\AccessKey\AccessTokenEnum;
10
use Uxmp\Core\Orm\Repository\AccessKeyRepositoryInterface;
11
use Uxmp\Core\Orm\Repository\UserRepositoryInterface;
12
13
/**
14
 * Provides auth mechanism for subsonic api auth
15
 */
16
final class AuthenticationProvider implements AuthenticationProviderInterface
17
{
18
    public function __construct(
19
        private UserRepositoryInterface $userRepository,
20
        private AccessKeyRepositoryInterface $accessKeyRepository,
21
    ) {
22
    }
23
24
    /**
25
     * Preferred way of auth, using a hashed version of the access token
26
     *
27
     * @throws AuthenticationFailedException
28
     */
29
    public function authByToken(
30
        string $userName,
31
        string $token,
32
        string $salt,
33
    ): void {
34
        $accessKeyFromStorage = $this->retrieveToken($userName);
35
36
        // use the provided salt to hash the token
37
        if (
38
            $accessKeyFromStorage === null ||
39
            $token !== md5($accessKeyFromStorage.$salt)
40
        ) {
41
            throw new AuthenticationFailedException();
42
        }
43
    }
44
45
    /**
46
     * Wah! Support for plaintext/hex encoded auth :(
47
     */
48
    public function authByPassword(
49
        string $userName,
50
        string $password,
51
    ): void {
52
        $accessKeyFromStorage = $this->retrieveToken($userName);
53
54
        if (
55
            $accessKeyFromStorage === null ||
56
            $password !== $accessKeyFromStorage
57
        ) {
58
            throw new AuthenticationFailedException();
59
        }
60
    }
61
62
    private function retrieveToken(
63
        string $userName,
64
    ): ?string {
65
        $user = $this->userRepository->findOneBy(['name' => $userName]);
66
        if ($user === null) {
67
            return null;
68
        }
69
70
        // search for a valid subsonic token
71
        $accessKey = $this->accessKeyRepository->findOneBy([
72
            'user' => $user,
73
            'type_id' => AccessTokenEnum::TYPE_SUBSONIC,
74
            'active' => true,
75
        ]);
76
77
        return $accessKey?->getConfig()[AccessTokenEnum::CONFIG_KEY_TOKEN] ?? null;
78
    }
79
}
80