Completed
Push — master ( 2370df...646536 )
by Tobias
11:34
created

SSOToken::__serialize()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 0
cts 7
cp 0
rs 9.8333
c 0
b 0
f 0
cc 3
nc 4
nop 0
crap 12
1
<?php
2
3
namespace Happyr\Auth0Bundle\Security\Authentication\Token;
4
5
use Happyr\Auth0Bundle\Model\Authentication\UserProfile\UserInfo;
6
use Happyr\Auth0Bundle\Model\Authorization\Token\Token;
7
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
8
use Symfony\Component\Security\Core\Role\Role;
9
10
class SSOToken extends AbstractToken
11
{
12
    /**
13
     * @var Token|null
14
     */
15
    private $auth0Data;
16
17
    /**
18
     * @var array
19
     */
20
    private $storedRoles = [];
21
22
    /**
23
     * The user model for the API.
24
     *
25
     * @var mixed
26
     */
27
    private $userModel;
28
29
    public function setAuth0Data(Token $data)
30
    {
31
        $this->auth0Data = $data;
32
    }
33
34
    public function getAuth0Data(): ?Token
35
    {
36
        return $this->auth0Data;
37
    }
38
39
    public function getAccessToken(): ?string
40
    {
41
        if (null === $this->auth0Data) {
42
            return null;
43
        }
44
45
        return $this->auth0Data->getAccessToken();
46
    }
47
48
    public function getExpiresAt(): ?\DateTimeInterface
49
    {
50
        if (null === $this->auth0Data) {
51
            return null;
52
        }
53
54
        return $this->auth0Data->getExpiresAt();
55
    }
56
57
    public function getUserModel(): ?UserInfo
58
    {
59
        return $this->userModel;
60
    }
61
62
    public function setUserModel(UserInfo $userModel)
63
    {
64
        $this->userModel = $userModel;
65
    }
66
67
    public function getCredentials()
68
    {
69
        return '';
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    public function __serialize(): array
76
    {
77
        $user = $this->getUser();
78
79
        return [
80
            is_object($user) ? clone $user : $user,
81
            is_object($this->userModel) ? clone $this->userModel : $this->userModel,
82
            $this->isAuthenticated(),
83
            $this->getRoles(),
0 ignored issues
show
Deprecated Code introduced by
The method Happyr\Auth0Bundle\Secur...en\SSOToken::getRoles() has been deprecated.

This method has been deprecated.

Loading history...
84
            $this->getAttributes(),
85
            $this->auth0Data,
86
        ];
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function __unserialize(array $data): void
93
    {
94
        [$user, $this->userModel, $isAuthenticated, $this->storedRoles, $attributes, $auth0Data] = $data;
0 ignored issues
show
Bug introduced by
The variable $user does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $isAuthenticated does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $attributes does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $auth0Data does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
95
        if ($user) {
96
            $this->setUser($user);
97
        }
98
99
        if ($auth0Data instanceof Token) {
100
            $this->setAuth0Data($auth0Data);
101
        }
102
103
        $this->setAuthenticated($isAuthenticated);
104
        $this->setAttributes($attributes);
105
    }
106
107
    public function getRoleNames(): array
108
    {
109
        $allRoles = array_merge(parent::getRoleNames(), $this->storedRoles);
110
        $uniqueRoles = [];
111
112
        /** @var Role $role */
113
        foreach ($allRoles as $role) {
114
            $name = is_string($role) ? $role : $role->getRole();
115
            $uniqueRoles[$name] = true;
116
        }
117
118
        return array_keys($uniqueRoles);
119
    }
120
121
    /**
122
     * This function is deprecated by Symfony 4.3.
123
     *
124
     * @deprecated
125
     */
126
    public function getRoles()
127
    {
128
        // To avoid any Symfony deprecation notices created by Symfony
129
        if (0 === \func_num_args()) {
130
            $parentRoles = parent::getRoles();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\Securi...ion\Token\AbstractToken as the method getRoles() does only exist in the following sub-classes of Symfony\Component\Securi...ion\Token\AbstractToken: Happyr\Auth0Bundle\Secur...tication\Token\SSOToken. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
131
        } else {
132
            $parentRoles = parent::getRoles(func_get_arg(0));
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\Securi...ion\Token\AbstractToken as the method getRoles() does only exist in the following sub-classes of Symfony\Component\Securi...ion\Token\AbstractToken: Happyr\Auth0Bundle\Secur...tication\Token\SSOToken. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
133
        }
134
135
        $allRoles = array_merge($parentRoles, $this->storedRoles);
136
        $uniqueRoles = [];
137
138
        /** @var Role $role */
139
        foreach ($allRoles as $role) {
140
            $uniqueRoles[$role->getRole()] = $role;
141
        }
142
143
        return array_values($uniqueRoles);
144
    }
145
}
146