mad-web /
laravel-social-auth
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace MadWeb\SocialAuth\Controllers; |
||
| 4 | |||
| 5 | use Exception; |
||
| 6 | use Illuminate\Http\Request; |
||
| 7 | use Illuminate\Contracts\Auth\Guard; |
||
| 8 | use MadWeb\SocialAuth\Models\SocialProvider; |
||
| 9 | use MadWeb\SocialAuth\SocialProviderManager; |
||
| 10 | use Illuminate\Foundation\Bus\DispatchesJobs; |
||
| 11 | use Illuminate\Contracts\Auth\Authenticatable; |
||
| 12 | use Illuminate\Foundation\Auth\RedirectsUsers; |
||
| 13 | use MadWeb\SocialAuth\Events\SocialUserDetached; |
||
| 14 | use Laravel\Socialite\Contracts\User as SocialUser; |
||
| 15 | use Illuminate\Routing\Controller as BaseController; |
||
| 16 | use Laravel\Socialite\Contracts\Factory as Socialite; |
||
| 17 | use MadWeb\SocialAuth\Events\SocialUserAuthenticated; |
||
| 18 | use Illuminate\Foundation\Validation\ValidatesRequests; |
||
| 19 | use Illuminate\Foundation\Auth\Access\AuthorizesRequests; |
||
| 20 | use MadWeb\SocialAuth\Exceptions\SocialUserAttachException; |
||
| 21 | use MadWeb\SocialAuth\Exceptions\SocialGetUserInfoException; |
||
| 22 | |||
| 23 | /** |
||
| 24 | * Class SocialAuthController. |
||
| 25 | */ |
||
| 26 | class SocialAuthController extends BaseController |
||
| 27 | { |
||
| 28 | use AuthorizesRequests, |
||
| 29 | DispatchesJobs, |
||
| 30 | ValidatesRequests, |
||
| 31 | RedirectsUsers; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * Redirect path. |
||
| 35 | * |
||
| 36 | * @var string |
||
| 37 | */ |
||
| 38 | protected $redirectTo = '/'; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @var Guard auth provider instance |
||
| 42 | */ |
||
| 43 | protected $auth; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * @var Socialite |
||
| 47 | */ |
||
| 48 | protected $socialite; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * @var \MadWeb\SocialAuth\Contracts\SocialAuthenticatable|\Illuminate\Contracts\Auth\Authenticatable |
||
| 52 | */ |
||
| 53 | protected $userModel; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @var SocialProviderManager |
||
| 57 | */ |
||
| 58 | protected $manager; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * SocialAuthController constructor. Register Guard contract dependency. |
||
| 62 | * |
||
| 63 | * @param Guard $auth |
||
| 64 | * @param Socialite $socialite |
||
| 65 | */ |
||
| 66 | 48 | public function __construct(Guard $auth, Socialite $socialite) |
|
| 67 | { |
||
| 68 | 48 | $this->auth = $auth; |
|
| 69 | 48 | $this->socialite = $socialite; |
|
| 70 | 48 | $this->redirectTo = config('social-auth.redirect'); |
|
| 71 | |||
| 72 | 48 | $className = config('social-auth.models.user'); |
|
| 73 | 48 | $this->userModel = new $className; |
|
| 74 | |||
| 75 | 48 | $this->middleware(function ($request, $next) { |
|
| 76 | 48 | $this->manager = new SocialProviderManager($request->route('social')); |
|
| 77 | |||
| 78 | 48 | return $next($request); |
|
| 79 | 48 | }); |
|
| 80 | 48 | } |
|
| 81 | |||
| 82 | /** |
||
| 83 | * If there is no response from the social network, redirect the user to the social auth page |
||
| 84 | * else make create with information from social network. |
||
| 85 | * |
||
| 86 | * @param SocialProvider $social bound by "Route model binding" feature |
||
| 87 | * @return \Symfony\Component\HttpFoundation\RedirectResponse |
||
| 88 | */ |
||
| 89 | 3 | public function getAccount(SocialProvider $social) |
|
| 90 | { |
||
| 91 | 3 | $provider = $this->socialite->driver($social->slug); |
|
| 92 | |||
| 93 | 3 | if (! empty($social->scopes)) { |
|
| 94 | $social->override_scopes ? $provider->setScopes($social->scopes) : $provider->scopes($social->scopes); |
||
| 95 | } |
||
| 96 | |||
| 97 | 3 | return empty($social->parameters) ? $provider->redirect() : $provider->with($social->parameters)->redirect(); |
|
| 98 | } |
||
| 99 | |||
| 100 | /** |
||
| 101 | * Redirect callback for social network. |
||
| 102 | * |
||
| 103 | * @param Request $request |
||
| 104 | * @param SocialProvider $social |
||
| 105 | * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector |
||
| 106 | * @throws SocialGetUserInfoException |
||
| 107 | * @throws SocialUserAttachException |
||
| 108 | */ |
||
| 109 | 33 | public function callback(Request $request, SocialProvider $social) |
|
| 110 | { |
||
| 111 | 33 | $provider = $this->socialite->driver($social->slug); |
|
| 112 | |||
| 113 | 33 | $SocialUser = null; |
|
| 114 | |||
| 115 | // try to get user info from social network |
||
| 116 | try { |
||
| 117 | 33 | $SocialUser = $social->stateless ? $provider->stateless()->user() : $provider->user(); |
|
| 118 | 3 | } catch (Exception $e) { |
|
| 119 | 3 | throw new SocialGetUserInfoException($social, $e->getMessage()); |
|
| 120 | } |
||
| 121 | |||
| 122 | // if we have no social info for some reason |
||
| 123 | 30 | if (! $SocialUser) { |
|
| 124 | 3 | throw new SocialGetUserInfoException( |
|
| 125 | 3 | $social, |
|
| 126 | 3 | trans('social-auth::messages.no_user_data', ['social' => $social->label]) |
|
| 127 | ); |
||
| 128 | } |
||
| 129 | |||
| 130 | // if user is guest |
||
| 131 | 27 | if (! $this->auth->check()) { |
|
| 132 | 18 | return $this->processData($request, $social, $SocialUser); |
|
| 133 | } |
||
| 134 | |||
| 135 | 9 | $redirect_path = $this->redirectPath(); |
|
| 136 | 9 | $User = $request->user(); |
|
| 137 | |||
| 138 | // if user already attached |
||
| 139 | 9 | if ($User->isAttached($social->slug)) { |
|
| 140 | 3 | throw new SocialUserAttachException( |
|
| 141 | 3 | redirect($redirect_path) |
|
| 142 | 3 | ->withErrors(trans('social-auth::messages.user_already_attach', ['social' => $social->label])), |
|
| 143 | 3 | $social |
|
| 144 | ); |
||
| 145 | } |
||
| 146 | |||
| 147 | //If someone already attached current socialProvider account |
||
| 148 | 6 | if ($this->manager->socialUserQuery($SocialUser->getId())->exists()) { |
|
| 149 | 3 | throw new SocialUserAttachException( |
|
| 150 | 3 | redirect($redirect_path) |
|
| 151 | 3 | ->withErrors(trans('social-auth::messages.someone_already_attach')), |
|
| 152 | 3 | $social |
|
| 153 | ); |
||
| 154 | } |
||
| 155 | |||
| 156 | 3 | $this->manager->attach($User, $SocialUser); |
|
| 157 | |||
| 158 | 3 | return redirect($redirect_path); |
|
| 159 | } |
||
| 160 | |||
| 161 | /** |
||
| 162 | * Detaches social account for user. |
||
| 163 | * |
||
| 164 | * @param Request $request |
||
| 165 | * @param SocialProvider $social |
||
| 166 | * @return array |
||
| 167 | * @throws SocialUserAttachException |
||
| 168 | */ |
||
| 169 | 12 | public function detachAccount(Request $request, SocialProvider $social) |
|
| 170 | { |
||
| 171 | /** @var \MadWeb\SocialAuth\Contracts\SocialAuthenticatable $User */ |
||
| 172 | 12 | $User = $request->user(); |
|
| 173 | 12 | $UserSocials = $User->socials(); |
|
| 174 | |||
| 175 | 12 | if ($UserSocials->count() === 1 and empty($User->{$User->getEmailField()})) { |
|
|
0 ignored issues
–
show
|
|||
| 176 | 3 | throw new SocialUserAttachException( |
|
| 177 | 3 | back()->withErrors(trans('social-auth::messages.detach_error_last')), |
|
| 178 | 3 | $social |
|
| 179 | ); |
||
| 180 | } |
||
| 181 | |||
| 182 | 9 | $result = $UserSocials->detach($social->id); |
|
| 183 | |||
| 184 | 9 | if (! $result) { |
|
| 185 | 3 | throw new SocialUserAttachException( |
|
| 186 | 3 | back()->withErrors(trans('social-auth::messages.detach_error', ['social' => $social->label])), |
|
| 187 | 3 | $social |
|
| 188 | ); |
||
| 189 | } |
||
| 190 | |||
| 191 | 6 | event(new SocialUserDetached($User, $social, $result)); |
|
|
0 ignored issues
–
show
$result is of type integer, but the function expects a boolean.
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
| 192 | |||
| 193 | 6 | return redirect($this->redirectPath()); |
|
| 194 | } |
||
| 195 | |||
| 196 | /** |
||
| 197 | * Process user using data from social network. |
||
| 198 | * |
||
| 199 | * @param Request $request |
||
| 200 | * @param SocialProvider $social |
||
| 201 | * @param SocialUser $socialUser |
||
| 202 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector |
||
| 203 | */ |
||
| 204 | 18 | protected function processData(Request $request, SocialProvider $social, SocialUser $socialUser) |
|
| 205 | { |
||
| 206 | //Checks by socialProvider identifier if user exists |
||
| 207 | 18 | $ExistUser = $this->manager->getUserByKey($socialUser->getId()); |
|
| 208 | 18 | $redirect_path = $this->redirectPath(); |
|
| 209 | |||
| 210 | //Checks if user exists with current socialProvider identifier, auth if does |
||
| 211 | 18 | if ($ExistUser) { |
|
| 212 | 6 | $this->login($ExistUser); |
|
| 213 | |||
| 214 | 6 | return redirect($redirect_path); |
|
| 215 | } |
||
| 216 | |||
| 217 | //Checks if account exists with socialProvider email, auth and attach current socialProvider if does |
||
| 218 | 12 | $ExistUser = $this->userModel->where($this->userModel->getEmailField(), $socialUser->getEmail())->first(); |
|
|
0 ignored issues
–
show
The method
getEmailField does only exist in MadWeb\SocialAuth\Contracts\SocialAuthenticatable, but not in Illuminate\Contracts\Auth\Authenticatable.
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
Loading history...
|
|||
| 219 | 12 | if ($ExistUser) { |
|
| 220 | 6 | $this->login($ExistUser); |
|
| 221 | |||
| 222 | 6 | $this->manager->attach($request->user(), $socialUser); |
|
| 223 | |||
| 224 | 6 | return redirect($redirect_path); |
|
| 225 | } |
||
| 226 | |||
| 227 | //If account for current socialProvider data doesn't exist - create new one |
||
| 228 | 6 | $NewUser = $this->manager->createNewUser($this->userModel, $social, $socialUser); |
|
|
0 ignored issues
–
show
It seems like
$this->userModel can also be of type object<MadWeb\SocialAuth...\SocialAuthenticatable>; however, MadWeb\SocialAuth\Social...anager::createNewUser() does only seem to accept object<Illuminate\Contracts\Auth\Authenticatable>, maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. Loading history...
|
|||
| 229 | 6 | $this->login($NewUser); |
|
| 230 | |||
| 231 | 6 | return redirect($redirect_path); |
|
| 232 | } |
||
| 233 | |||
| 234 | /** |
||
| 235 | * Login user. |
||
| 236 | * |
||
| 237 | * @param Authenticatable $user |
||
| 238 | */ |
||
| 239 | 18 | protected function login(Authenticatable $user) |
|
| 240 | { |
||
| 241 | 18 | $this->auth->login($user); |
|
|
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Illuminate\Contracts\Auth\Guard as the method login() does only exist in the following implementations of said interface: Illuminate\Auth\SessionGuard.
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
Loading history...
|
|||
| 242 | 18 | event(new SocialUserAuthenticated($user)); |
|
| 243 | 18 | } |
|
| 244 | } |
||
| 245 |
PHP has two types of connecting operators (logical operators, and boolean operators):
and&&or||The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like
&&, or||.Let’s take a look at a few examples:
Logical Operators are used for Control-Flow
One case where you explicitly want to use logical operators is for control-flow such as this:
Since
dieintroduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined withthrowat this point:These limitations lead to logical operators rarely being of use in current PHP code.