IdentityTrait   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 59
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 7.69%

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 4
dl 0
loc 59
ccs 2
cts 26
cp 0.0769
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getRestrictedScopes() 0 4 1
A setRestrictedScopes() 0 8 3
B findIdentityByAccessToken() 0 24 6
1
<?php
2
/**
3
 * IdentityTrait.php
4
 *
5
 * PHP version 5.6+
6
 *
7
 * @author Philippe Gaultier <[email protected]>
8
 * @copyright 2010-2017 Philippe Gaultier
9
 * @license http://www.sweelix.net/license license
10
 * @version 1.2.0
11
 * @link http://www.sweelix.net
12
 * @package sweelix\oauth2\server\traits
13
 */
14
15
namespace sweelix\oauth2\server\traits;
16
17
use OAuth2\Request;
18
use sweelix\oauth2\server\Module;
19
use Yii;
20
21
/**
22
 * Helper to build Identity management
23
 *
24
 * @author Philippe Gaultier <[email protected]>
25
 * @copyright 2010-2017 Philippe Gaultier
26
 * @license http://www.sweelix.net/license license
27
 * @version 1.2.0
28
 * @link http://www.sweelix.net
29
 * @package sweelix\oauth2\server\traits
30
 * @since 1.0.0
31
 */
32
trait IdentityTrait
33
{
34
35
    /**
36
     * @var array list of restricted scopes
37
     */
38
    private $scopes = null;
39
40
    /**
41
     * @return array list of restricted scopes
42
     */
43 3
    public function getRestrictedScopes()
44
    {
45 3
        return $this->scopes;
46
    }
47
48
    /**
49
     * @param array $scopes list of restricted scopes
50
     */
51
    public function setRestrictedScopes($scopes)
52
    {
53
        if (is_array($scopes) === true) {
54
            $this->scopes = $scopes;
55
        } elseif (empty($scopes) === false) {
56
            $this->scopes = [$scopes];
57
        }
58
    }
59
60
    /**
61
     * @param string $token token id
62
     * @param string $type type of token
63
     * @return \sweelix\oauth2\server\interfaces\UserModelInterface
64
     */
65
    public static function findIdentityByAccessToken($token, $type = null)
66
    {
67
        $identity = null;
68
        if (($type === 'yii\filters\auth\HttpBearerAuth') || ($type === 'yii\filters\auth\QueryParamAuth')) {
69
            // handle only bearer tokens
70
            $oauthServer = Yii::createObject('OAuth2\Server');
71
            /* @var \OAuth2\Server $oauthServer */
72
            $oauthRequest = Request::createFromGlobals();
73
            $oauthResponse = Yii::createObject('OAuth2\Response');
74
            // check if token is ok
75
            $result = $oauthServer->verifyResourceRequest($oauthRequest, $oauthResponse);
76
            $tokenData = $oauthServer->getResourceController()->getToken();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface OAuth2\Controller\ResourceControllerInterface as the method getToken() does only exist in the following implementations of said interface: OAuth2\Controller\ResourceController, OAuth2\OpenID\Controller\UserInfoController.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
77
            if (($result === true) && ($token === $tokenData['id_token'])) {
78
                $identityClass = Module::getInstance()->identityClass;
79
                // $identity = $identityClass::findByUsername($tokenData['user_id']);
80
                $identity = $identityClass::findIdentity($tokenData['user_id']);
81
                /* @var \sweelix\oauth2\server\interfaces\UserModelInterface $identity */
82
                if (empty($tokenData['scope']) === false) {
83
                    $identity->setRestrictedScopes(explode(' ', $tokenData['scope']));
84
                }
85
            }
86
        }
87
        return $identity;
88
    }
89
90
}
91