Completed
Push — develop ( 112c74...31322a )
by Nate
10:28
created

TokenHelper   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 4

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 17
lcom 0
cbo 4
dl 0
loc 149
ccs 0
cts 82
cp 0
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A parse() 0 18 5
A getSignatureKey() 0 10 3
A verifyTokenCsrfClaim() 0 13 2
A verifyTokenSignature() 0 19 3
A verifyAudience() 0 13 2
A verifyIssuer() 0 16 2
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/jwt/license
6
 * @link       https://www.flipboxfactory.com/jwt/organization/
7
 */
8
9
namespace flipbox\craft\jwt\helpers;
10
11
use Craft;
12
use craft\helpers\User;
13
use flipbox\craft\jwt\Jwt;
14
use Lcobucci\JWT\Token;
15
use yii\web\IdentityInterface;
16
17
/**
18
 * @author Flipbox Factory <[email protected]>
19
 * @since 1.0.0
20
 */
21
class TokenHelper
22
{
23
    /**
24
     * The CSRF claim identifier
25
     */
26
    const CLAIM_CSRF = 'csrf';
27
28
    /**
29
     * The Audience claim identifier
30
     */
31
    const CLAIM_AUDIENCE = 'aud';
32
33
    /**
34
     * The Issuer claim identifier
35
     */
36
    const CLAIM_ISSUER = 'iss';
37
38
    /**
39
     * The Identity claim identifier
40
     */
41
    const CLAIM_IDENTITY = 'jti';
42
43
    /**
44
     * @param $token
45
     * @param bool $validate
46
     * @return Token|null
47
     * @throws \craft\errors\SiteNotFoundException
48
     */
49
    public static function parse(string $token, bool $validate = true)
50
    {
51
        try {
52
            $token = Jwt::getInstance()->getParser()->parse((string)$token);
53
        } catch (\RuntimeException $e) {
54
            Jwt::warning("Invalid JWT provided: " . $e->getMessage());
55
            return null;
56
        } catch (\InvalidArgumentException $e) {
57
            Jwt::warning("Invalid JWT provided: " . $e->getMessage());
58
            return null;
59
        }
60
61
        if ($validate && !Jwt::getInstance()->validateToken($token)) {
62
            return null;
63
        }
64
65
        return $token;
66
    }
67
68
    /**
69
     * @param IdentityInterface $identity
70
     * @return string
71
     */
72
    public static function getSignatureKey(IdentityInterface $identity = null)
73
    {
74
        $result = Jwt::getInstance()->getSettings()->getKey();
75
76
        if ($identity === null) {
77
            return $result;
78
        }
79
80
        return $result . '.' . $identity instanceof User ? $identity->uid : $identity->getId();
0 ignored issues
show
Bug introduced by
Accessing uid on the interface yii\web\IdentityInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
The class craft\helpers\User does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
81
    }
82
83
    /**
84
     * @param Token $token
85
     * @return bool
86
     */
87
    public static function verifyTokenCsrfClaim(Token $token): bool
88
    {
89
        $csrf = $token->getClaim(self::CLAIM_CSRF);
90
        if (false === Craft::$app->getRequest()->validateCsrfToken($csrf)) {
91
            Jwt::error(sprintf(
92
                "Unable to verify CSRF Token: %s",
93
                $csrf
94
            ));
95
96
            return false;
97
        }
98
        return true;
99
    }
100
101
    /**
102
     * @param Token $token
103
     * @param IdentityInterface $identity
104
     * @return bool
105
     */
106
    public static function verifyTokenSignature(Token $token, IdentityInterface $identity = null): bool
107
    {
108
        try {
109
            if (false === $token->verify(
110
                    Jwt::getInstance()->getSettings()->resolveSigner($token->getHeader('alg')),
111
                    TokenHelper::getSignatureKey($identity)
112
                )) {
113
                Jwt::error("Unable to verify token signature");
114
                return false;
115
            }
116
            return true;
117
        } catch (\Exception $e) {
118
            Jwt::error(sprintf(
119
                "Exception caught while trying to verify token signature: %s",
120
                $e->getMessage()
121
            ));
122
        }
123
        return false;
124
    }
125
126
    /**
127
     * @param Token $token
128
     * @return bool
129
     * @throws \craft\errors\SiteNotFoundException
130
     */
131
    public static function verifyAudience(Token $token): bool
132
    {
133
        $audience = $token->getClaim(TokenHelper::CLAIM_AUDIENCE);
134
        if (false === ($audience === Craft::$app->getSites()->getCurrentSite()->getBaseUrl())) {
135
            Jwt::error(sprintf(
136
                "Unable to verify audience: %s",
137
                $audience
138
            ));
139
140
            return false;
141
        }
142
        return true;
143
    }
144
145
    /**
146
     * Verify that the issuer is one we can accept from
147
     *
148
     * @param Token $token
149
     * @param array $issuers
150
     * @return bool
151
     * @throws \craft\errors\SiteNotFoundException
152
     */
153
    public static function verifyIssuer(Token $token, array $issuers): bool
154
    {
155
        $issuer = $token->getClaim(TokenHelper::CLAIM_ISSUER);
156
        if (false === in_array(
157
                $issuer,
158
                $issuers
159
            )) {
160
            Jwt::error(sprintf(
161
                "Unable to verify issuer: %s",
162
                $issuer
163
            ));
164
165
            return false;
166
        }
167
        return true;
168
    }
169
}