Completed
Push — master ( 059364...3a1470 )
by Bukashk0zzz
03:01
created

Security/JWTUserProvider.php (1 issue)

1
<?php declare(strict_types = 1);
2
3
namespace AtlassianConnectBundle\Security;
4
5
use AtlassianConnectBundle\Entity\Tenant;
6
use Doctrine\Common\Persistence\ManagerRegistry;
7
use Doctrine\ORM\EntityManager;
8
use Firebase\JWT\JWT;
9
use Symfony\Component\Security\Core\Exception\AuthenticationException;
10
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
11
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
12
use Symfony\Component\Security\Core\User\UserInterface;
13
use Symfony\Component\Security\Core\User\UserProviderInterface;
14
15
/**
16
 * Class JWTUserProvider
17
 */
18
class JWTUserProvider implements UserProviderInterface
19
{
20
    /**
21
     * @var EntityManager
22
     */
23
    protected $em;
24
25
    /**
26
     * @var int
27
     */
28
    protected $tokenLifetime;
29
30
    /**
31
     * @var string
32
     */
33
    protected $tenantClass;
34
35
    /**
36
     * JWTUserProvider constructor.
37
     *
38
     * @param ManagerRegistry $registry
39
     * @param int             $tokenLifetime
40
     * @param string          $tenantClass
41
     */
42
    public function __construct(ManagerRegistry $registry, int $tokenLifetime, string $tenantClass)
43
    {
44
        $this->em = $registry->getManager();
45
        $this->tokenLifetime = $tokenLifetime;
46
        $this->tenantClass = $tenantClass;
47
    }
48
49
    /**
50
     * @param string $jwt
51
     *
52
     * @return mixed
53
     */
54
    public function getDecodedToken(string $jwt)
55
    {
56
        try {
57
            /** @noinspection PhpUnusedLocalVariableInspection */
58
            [$headb64, $bodyb64, $cryptob64] = \explode('.', $jwt);
59
            $decodedToken = \json_decode(JWT::urlsafeB64Decode($bodyb64));
60
61
            $tenant = $this->findTenant($decodedToken->iss);
62
63
            JWT::decode($jwt, $tenant->getSharedSecret(), ['HS256']);
64
65
            return $decodedToken;
66
        } catch (\Throwable $e) {
67
            throw new AuthenticationException($e->getMessage());
68
        }
69
    }
70
71
    /**
72
     * @param mixed $clientKey
73
     *
74
     * @return Tenant
75
     */
76
    public function loadUserByUsername($clientKey): Tenant
77
    {
78
        $tenant = $this->findTenant($clientKey);
79
        if (!$tenant) {
80
            throw new UsernameNotFoundException('Can\'t find tenant with such username');
81
        }
82
83
        return $this->findTenant($clientKey);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->findTenant($clientKey) could return the type null which is incompatible with the type-hinted return AtlassianConnectBundle\Entity\Tenant. Consider adding an additional type-check to rule them out.
Loading history...
84
    }
85
86
    /**
87
     * @param UserInterface $user
88
     */
89
    public function refreshUser(UserInterface $user): void
90
    {
91
        throw new UnsupportedUserException('Refresh prohibited');
92
    }
93
94
    /**
95
     * @param string|mixed $class
96
     *
97
     * @return bool
98
     */
99
    public function supportsClass($class): bool
100
    {
101
        return ($class === 'AtlassianConnectBundle\Entity\Tenant') || \is_subclass_of($class, Tenant::class);
102
    }
103
104
    /**
105
     * @param string $clientKey
106
     *
107
     * @return Tenant|null
108
     */
109
    protected function findTenant(string $clientKey): ?Tenant
110
    {
111
        /** @noinspection PhpUndefinedMethodInspection */
112
113
        return $this->em
114
            ->getRepository($this->tenantClass)
115
            ->findOneByClientKey($clientKey);
116
    }
117
}
118