Completed
Push — release-v2.1 ( f3e4d5...4af3af )
by Quentin
02:51
created

AccessTokenAuthenticator::start()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 1
nc 1
nop 2
1
<?php
2
3
namespace Majora\Bundle\OAuthServerBundle\Security;
4
5
use Majora\Component\OAuth\Exception\InvalidAccessTokenException;
6
use Majora\Component\OAuth\Server\Server as OAuthServer;
7
use Symfony\Component\HttpFoundation\JsonResponse;
8
use Symfony\Component\HttpFoundation\Request;
9
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
10
use Symfony\Component\Security\Core\Exception\AuthenticationException;
11
use Symfony\Component\Security\Core\User\UserInterface;
12
use Symfony\Component\Security\Core\User\UserProviderInterface;
13
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
14
15
/**
16
 * AccessToken authenticator class using Guard Symfony component and OAuth server.
17
 *
18
 * @link https://knpuniversity.com/screencast/guard/api-token
19
 */
20
class AccessTokenAuthenticator extends AbstractGuardAuthenticator
21
{
22
    /**
23
     * @var OAuthServer
24
     */
25
    protected $oauthServer;
26
27
    /**
28
     * @var AccessTokenInterface
29
     */
30
    protected $currentAccessToken;
31
32
    /**
33
     * Construct.
34
     *
35
     * @param OAuthServer $oauthServer
36
     */
37
    public function __construct(OAuthServer $oauthServer)
38
    {
39
        $this->oauthServer = $oauthServer;
40
    }
41
42
    /**
43
     * @see GuardAuthenticatorInterface::getCredentials()
44
     */
45
    public function getCredentials(Request $request)
46
    {
47
        switch (true) {
48
49
            // token through query params
50
            case $request->query->has('access_token') :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
51
                $hash = $request->query->get('access_token');
52
            break;
53
54
            // token through headers
55
            case $request->headers->has('Authorization') :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
56
                if (!preg_match('#^Bearer ([\w]+)$#', $request->headers->get('Authorization'), $matches)) {
57
                    break; // bad Authorization format
58
                }
59
60
                $hash = $matches[1];
61
            break;
62
63
            // otherwise auth failed
64
            default:
65
                return;
66
        }
67
68
        try {
69
            return $this->currentAccessToken = $this->oauthServer->check($hash);
0 ignored issues
show
Bug introduced by
The variable $hash does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Documentation Bug introduced by
It seems like $this->oauthServer->check($hash) of type object<Majora\Component\...\Loader\TokenInterface> is incompatible with the declared type object<Majora\Bundle\OAu...y\AccessTokenInterface> of property $currentAccessToken.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
70
        } catch (InvalidAccessTokenException $e) {
71
            // log there
72
        }
73
    }
74
75
    /**
76
     * @see GuardAuthenticatorInterface::getUser()
77
     */
78
    public function getUser($accessToken, UserProviderInterface $userProvider)
79
    {
80
        return $accessToken->getAccount();
81
    }
82
83
    /**
84
     * @see GuardAuthenticatorInterface::checkCredentials()
85
     */
86
    public function checkCredentials($accessToken, UserInterface $user)
87
    {
88
        // test here if access token is valid (expiration date etc...)
89
        // or api limit isnt crossed
90
        // or anonymous allowed
91
        // etc...
92
    }
93
94
    /**
95
     * @see GuardAuthenticatorInterface::onAuthenticationSuccess()
96
     */
97
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
98
    {
99
        $request->query->remove('access_token');
100
        $request->headers->remove('Authorization');
101
        $request->attributes->set('access_token', $this->currentAccessToken);
102
    }
103
104
    /**
105
     * @see GuardAuthenticatorInterface::onAuthenticationFailure()
106
     */
107
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
108
    {
109
        return new JsonResponse(
110
            array('message' => 'OAuth authentication required.'),
111
            403
112
        );
113
    }
114
115
    /**
116
     * @see GuardAuthenticatorInterface::onAuthenticationFailure()
117
     */
118
    public function start(Request $request, AuthenticationException $authException = null)
119
    {
120
        // if anonymous granted
121
    }
122
123
    /**
124
     * @see GuardAuthenticatorInterface::supportsRememberMe()
125
     */
126
    public function supportsRememberMe()
127
    {
128
        return false;
129
    }
130
}
131