Passed
Pull Request — master (#52)
by Matthieu
04:51
created

JWTSecurityHelper::findTenantJWT()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 14
nc 3
nop 1
dl 0
loc 21
rs 9.7998
c 1
b 0
f 0
1
<?php declare(strict_types = 1);
2
3
namespace AtlassianConnectBundle\Security;
4
5
use AtlassianConnectBundle\Service\QSHGenerator;
6
use Doctrine\ORM\EntityManagerInterface;
7
use Firebase\JWT\JWT;
8
use Symfony\Component\HttpFoundation\Request;
9
10
/**
11
 * Class JWTSecurityHelper
12
 */
13
final class JWTSecurityHelper implements JWTSecurityHelperInterface
14
{
15
    /**
16
     * @var EntityManagerInterface
17
     */
18
    private $entityManager;
19
20
    /**
21
     * @var int|null
22
     */
23
    private $devTenant;
24
25
    /**
26
     * @var string
27
     */
28
    private $environment;
29
30
    /**
31
     * @var string
32
     */
33
    private $tenantEntityClass;
34
35
    /**
36
     * JWTSecurityHelper constructor.
37
     *
38
     * @param EntityManagerInterface $entityManager
39
     * @param int|null               $devTenant
40
     * @param string                 $environment
41
     * @param string                 $tenantEntityClass
42
     */
43
    public function __construct(
44
        EntityManagerInterface $entityManager,
45
        ?int $devTenant,
46
        string $environment,
47
        string $tenantEntityClass
48
    ) {
49
        $this->entityManager = $entityManager;
50
        $this->devTenant = $devTenant;
51
        $this->environment = $environment;
52
        $this->tenantEntityClass = $tenantEntityClass;
53
    }
54
55
    /**
56
     * @param Request $request
57
     *
58
     * @return bool
59
     */
60
    public function supportsRequest(Request $request): bool
61
    {
62
        return $request->query->has('jwt') ||
63
            $request->headers->has('authorization') ||
64
            ($this->devTenant && $this->environment === 'dev');
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->devTenant of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
65
    }
66
67
    /**
68
     * @param Request $request
69
     *
70
     * @return string|null
71
     */
72
    public function getJWTToken(Request $request): ?string
73
    {
74
        if ($request->query->has('jwt')) {
75
            return (string) $request->query->get('jwt');
76
        }
77
78
        $headerJWT = $this->findJWTInHeader($request);
79
80
        if ($headerJWT) {
81
            return $headerJWT;
82
        }
83
84
        return $this->findTenantJWT($request);
85
    }
86
87
    /**
88
     * @param Request $request
89
     *
90
     * @return string|null
91
     */
92
    private function findJWTInHeader(Request $request): ?string
93
    {
94
        if ($request->headers->has('authorization')) {
95
            $authorizationHeaderArray = \explode(' ', $request->headers->get('authorization'));
96
97
            if (\count($authorizationHeaderArray) > 1) {
98
                return $authorizationHeaderArray[1];
99
            }
100
        }
101
102
        return null;
103
    }
104
105
    /**
106
     * @param Request $request
107
     *
108
     * @return string|null
109
     */
110
    private function findTenantJWT(Request $request): ?string
111
    {
112
        if (!$this->devTenant || $this->environment  !== 'dev') {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->devTenant of type integer|null is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
113
            return null;
114
        }
115
116
        $tenant = $this->entityManager
117
            ->getRepository($this->tenantEntityClass)
118
            ->find($this->devTenant);
119
120
        if (!$tenant) {
121
            throw new \RuntimeException(\sprintf('Cant find tenant with id %s - please set atlassian_connect.dev_tenant to false to disable dedicated dev tenant OR add valid id', $this->devTenant));
122
        }
123
124
        return JWT::encode([
125
            'iss' => $tenant->getClientKey(),
126
            'iat' => \time(),
127
            'exp' => \strtotime('+1 day'),
128
            'qsh' => QSHGenerator::generate($request->getRequestUri(), 'GET'),
129
            'sub' => 'admin',
130
        ], $tenant->getSharedSecret());
131
    }
132
}
133