GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

AuthComponent   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 199
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 28
lcom 1
cbo 7
dl 0
loc 199
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
B startup() 0 16 5
A unauthenticated() 0 11 3
A unauthorized() 0 3 1
A authenticate() 0 3 1
A authorize() 0 3 1
B check() 0 22 5
A isLoggedIn() 0 12 3
A _ControllerAuthorize() 0 7 2
A _UserAuthenticate() 0 12 3
A loggedIn() 0 20 3
A concurentSession() 0 3 1
1
<?php
2
3
/**
4
 * Authentication & Authorization component class.
5
 *
6
 * Authenticate & Authorize the current user.
7
 *
8
 * @license    http://opensource.org/licenses/MIT The MIT License (MIT)
9
 * @author     Omar El Gabry <[email protected]>
10
 */
11
12
class AuthComponent extends Component{
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
13
14
    /**
15
     * Default configurations
16
     *
17
     * @var array
18
     */
19
    protected $config = [
20
        'authenticate' => [],
21
        'authorize' => []
22
    ];
23
24
    /**
25
     * Auth startup
26
     * All authentication and authorization checking are done in this method
27
     *
28
     */
29
    public function startup(){
30
31
         // authenticate
32
         if(!empty($this->config["authenticate"])){
33
             if(!$this->authenticate()){
34
                 return $this->unauthenticated();
35
             }
36
         }
37
38
         // authorize
39
         if(!empty($this->config["authorize"])){
40
             if(!$this->authorize()){
41
                 return $this->unauthorized();
42
             }
43
         }
44
     }
45
46
    /**
47
     * Handles unauthenticated access attempt.
48
     *
49
     */
50
    public function unauthenticated(){
51
52
        $this->controller->login->logOut(Session::getUserId());
0 ignored issues
show
Documentation introduced by
The property login does not exist on object<Controller>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
53
54
        if($this->request->isAjax()) { 
55
            return $this->controller->error(401); 
56
        }else{
57
            $redirect = $this->controller->request->isGet()? $this->controller->request->uri(): "";
58
            return $this->controller->redirector->login($redirect); 
59
        }
60
    }
61
62
    /**
63
     * Handles unauthorized access attempt.
64
     *
65
     */
66
    public function unauthorized(){
67
        return $this->controller->error(403);
68
    }
69
70
     /**
71
      * authenticate the user using the defined methods in $config
72
      *
73
      * @return boolean
74
      */
75
     public function authenticate(){
76
         return $this->check($this->config["authenticate"], "authenticate");
77
     }
78
79
     /**
80
      * authorize the user using the defined methods in $config
81
      *
82
      * @return boolean
83
      */
84
    public function authorize(){
85
        return $this->check($this->config["authorize"], "authorize");
86
    }
87
88
     /**
89
      * check for authentication or authorization
90
      *
91
      * @param  array  $config
92
      * @param  string $type
93
      * @throws Exception if $config is empty or method doesn't exists
94
      * @return boolean
95
      */
96
     private function check($config, $type){
97
98
         if (empty($config)) {
99
             throw new Exception($type . ' methods arent initialized yet in config');
100
         }
101
102
         $auth = Utility::normalize($config);
103
104
         foreach($auth as $method => $config){
105
106
             $method = "_" . ucfirst($method) . ucfirst($type);
107
108
             if (!method_exists(__CLASS__, $method)) {
109
                 throw new Exception('Auth Method doesnt exists: ' . $method);
110
             }
111
112
             if($this->{$method}($config) === false){
113
                 return false;
114
             }
115
         }
116
        return true;
117
    }
118
119
    /**
120
     * Is user is already logged in via session or cookie?
121
     *
122
     * @return boolean
123
     */
124
    public function isLoggedIn(){
125
126
        if(Session::getIsLoggedIn() === true){
127
            return true;
128
        }
129
130
        if(Cookie::isCookieValid()){
131
            return true;
132
        }
133
134
        return false;
135
    }
136
137
     /**
138
      * Is user authorized for the requested Controller & Action method?
139
      *
140
      * @param array  $config  configuration data
141
      * @throws Exception if isAuthorized method doesn't exists in the controller class
142
      * @return boolean
143
      */
144
    private function _ControllerAuthorize($config){
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
145
146
        if (!method_exists($this->controller, 'isAuthorized')) {
147
            throw new Exception(sprintf('%s does not implement an isAuthorized() method.', get_class($this->controller)));
148
        }
149
        return (bool)$this->controller->isAuthorized();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Controller as the method isAuthorized() does only exist in the following sub-classes of Controller: AdminController, CommentsController, DownloadsController, FilesController, NewsFeedController, PostsController, TodoController, UserController. 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...
150
    }
151
152
     /**
153
      * Is user authenticated?
154
      * It checks for:
155
      *     - concurrent session
156
      *     - user credentials in session & cookies
157
      *     - cookies theft and manipulations
158
      *     - session Hijacking and fixation.
159
      *
160
      * @param array  $config  configuration data
161
      * @return boolean
162
      */
163
    private function _UserAuthenticate($config){
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
164
165
        if($this->concurentSession()){
166
            return false;
167
        }
168
169
        if(!$this->loggedIn()){
170
            return false;
171
        }
172
173
        return true;
174
    }
175
176
    /**
177
     * Checks if user is logged in or not.
178
     * It uses Session and Cookies to validate the current user.
179
     *
180
     * @access public
181
     * @static static method
182
     * @return boolean
183
     *
184
     */
185
    private function loggedIn(){
186
187
        if (Session::isSessionValid($this->request->clientIp(), $this->request->userAgent())) {
188
            return true;
189
        }
190
191
        if (Cookie::isCookieValid()) {
192
193
            // get role from user class, because cookies don't store roles
194
            $role = $this->controller->user->getProfileInfo(Cookie::getUserId())["role"];
0 ignored issues
show
Documentation introduced by
The property user does not exist on object<Controller>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
195
            Session::reset(["user_id" => Cookie::getUserId(), "role" => $role, "ip" => $this->request->clientIp(), "user_agent" => $this->request->userAgent()]);
196
197
            // reset cookie, Cookie token is usable only once
198
            Cookie::reset(Session::getUserId());
199
200
            return true;
201
        }
202
203
        return false;
204
    }
205
206
    private function concurentSession(){
207
        return Session::isConcurrentSessionExists();
208
    }
209
210
}
211