Completed
Pull Request — master (#45)
by Brian
06:00
created

AbstractProvider::setConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace SocialiteProviders\Manager\OAuth1;
4
5
use Laravel\Socialite\One\AbstractProvider as BaseProvider;
6
use SocialiteProviders\Manager\SocialiteWasCalled;
7
use SocialiteProviders\Manager\ConfigTrait;
8
use SocialiteProviders\Manager\Contracts\ConfigInterface as Config;
9
use Symfony\Component\HttpFoundation\RedirectResponse;
10
11
abstract class AbstractProvider extends BaseProvider
12
{
13
    use ConfigTrait;
14
15
    /**
16
     * Indicates if the session state should be utilized.
17
     *
18
     * @var bool
19
     */
20
    protected $stateless = true;
21
22
    /**
23
     * @var array
24
     */
25
    protected $credentialsResponseBody;
26
27
    public static function serviceContainerKey($providerName)
28
    {
29
        return SocialiteWasCalled::SERVICE_CONTAINER_PREFIX.$providerName;
30
    }
31
32
    /**
33
     * {@inheritdoc}
34
     */
35
    public function user()
36
    {
37
        if (!$this->hasNecessaryVerifier()) {
38
            throw new \InvalidArgumentException('Invalid request. Missing OAuth verifier.');
39
        }
40
41
        $token = $this->getToken();
42
        $tokenCredentials = $token['tokenCredentials'];
43
44
        $user = $this->mapUserToObject((array) $this->server->getUserDetails($tokenCredentials));
0 ignored issues
show
Bug introduced by
The method mapUserToObject() does not seem to exist on object<SocialiteProvider...Auth1\AbstractProvider>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
45
46
        $user->setToken($tokenCredentials->getIdentifier(), $tokenCredentials->getSecret());
47
48
        if ($user instanceof User) {
49
            parse_str($token['credentialsResponseBody'], $credentialsResponseBody);
50
51
            if (!$credentialsResponseBody || !is_array($credentialsResponseBody)) {
52
                throw new CredentialsException('Unable to parse token credentials response.');
53
            }
54
55
            $user->setAccessTokenResponseBody($credentialsResponseBody);
56
        }
57
58
        return $user;
59
    }
60
61
    /**
62
     * Redirect the user to the authentication page for the provider.
63
     *
64
     * @return RedirectResponse
65
     */
66
    public function redirect()
67
    {
68
        if (!$this->isStateless()) {
69
            $this->request->getSession()->set(
70
                'oauth.temp', $temp = $this->server->getTemporaryCredentials()
71
            );
72
        } else {
73
            $temp = $this->server->getTemporaryCredentials();
74
            setcookie('oauth_temp', serialize($temp));
75
        }
76
77
        return new RedirectResponse($this->server->getAuthorizationUrl($temp));
78
    }
79
80
    /**
81
     * Get the token credentials for the request.
82
     *
83
     * @return \League\OAuth1\Client\Credentials\TokenCredentials
84
     */
85
    protected function getToken()
0 ignored issues
show
Coding Style introduced by
getToken uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
86
    {
87
        if (!$this->isStateless()) {
88
            $temp = $this->request->getSession()->get('oauth.temp');
89
90
            return $this->server->getTokenCredentials(
91
                $temp, $this->request->get('oauth_token'), $this->request->get('oauth_verifier')
92
            );
93
        } else {
94
            $temp = unserialize($_COOKIE['oauth_temp']);
95
96
            return $this->server->getTokenCredentials(
97
                $temp, $this->request->get('oauth_token'), $this->request->get('oauth_verifier')
98
            );
99
        }
100
    }
101
102
    /**
103
     * Indicates that the provider should operate as stateless.
104
     *
105
     * @return $this
106
     */
107
    public function stateless()
108
    {
109
        $this->stateless = true;
110
111
        return $this;
112
    }
113
114
    /**
115
     * Determine if the provider is operating as stateless.
116
     *
117
     * @return bool
118
     */
119
    protected function isStateless()
120
    {
121
        if (defined('SOCIALITEPROVIDERS_STATELESS')) {
122
            return true;
123
        }
124
125
        return $this->stateless;
126
    }
127
128
    /**
129
     * Set the scopes of the requested access.
130
     *
131
     * @param array $scopes
132
     *
133
     * @return $this
134
     */
135
    public function scopes(array $scopes)
136
    {
137
        $this->server = $this->server->scopes($scopes);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class League\OAuth1\Client\Server\Server as the method scopes() does only exist in the following sub-classes of League\OAuth1\Client\Server\Server: SocialiteProviders\Manager\OAuth1\Server. 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...
138
139
        return $this;
140
    }
141
142
    /**
143
     * Set the custom parameters of the request.
144
     *
145
     * @param array $parameters
146
     *
147
     * @return $this
148
     */
149
    public function with(array $parameters)
150
    {
151
        $this->server = $this->server->with($parameters);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class League\OAuth1\Client\Server\Server as the method with() does only exist in the following sub-classes of League\OAuth1\Client\Server\Server: SocialiteProviders\Manager\OAuth1\Server. 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...
152
153
        return $this;
154
    }
155
156
    /**
157
     * @param Config $config
158
     *
159
     * @return $this
160
     */
161
    public function setConfig(Config $config)
162
    {
163
        $this->config = $this->server->setConfig($config);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class League\OAuth1\Client\Server\Server as the method setConfig() does only exist in the following sub-classes of League\OAuth1\Client\Server\Server: SocialiteProviders\Manager\OAuth1\Server. 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...
164
165
        return $this;
166
    }
167
}
168