middleware('guest', ['except' => 'logout']); } protected function attemptLogin(Request $request) { $isSuccessful = $this->guard()->attempt($this->credentials($request)); if ($isSuccessful) { /** @var User $user */ $user = $this->guard()->user(); // Update the social media ID if successful login and it was referred by the SSO provider $loginData = $request->getSession()->get('ssoLoginData'); if (!is_null($loginData)) { unset($loginData['name']); unset($loginData['email']); $user->fill($loginData); $user->save(); $request->getSession()->remove('ssoLoginData'); } } return $isSuccessful; } protected function credentials(Request $request) { $result = $request->only($this->username(), 'password'); // Only allow activated users to login $result['is_activated'] = true; return $result; } /** * Show the application's login form. * * @return \Illuminate\Http\Response */ public function showLoginForm(Request $request) { return Theme::render('auth.v2_unified', [ 'active_tab' => 'login', 'info' => $request->session()->get('info'), 'is_sso' => false ]); } /** * Show the application's login form (for a social media-linked account). * * @return \Illuminate\Http\Response */ public function showLoginFormSso(Request $request) { // Social media login info $loginData = $request->getSession()->get('ssoLoginData'); if (is_null($loginData)) { // No SSO data in session, use the normal login screen return redirect(route('login')); } return Theme::render('auth.v2_unified', [ 'active_tab' => 'login', 'info' => $request->session()->get('info'), 'is_sso' => true, 'login_data' => $loginData ]); } /** * Redirect the user to the Facebook authentication page. * * @return \Illuminate\Http\Response */ public function redirectToFacebook() { $socialite = $this->setSocialiteConfigs(); return $socialite->driver('facebook')->redirect(); } /** * Redirect the user to the Twitter authentication page. * * @return \Illuminate\Http\Response */ public function redirectToTwitter() { $socialite = $this->setSocialiteConfigs(); return $socialite->driver('twitter')->redirect(); } /** * Obtain the user information from Facebook. * * @return \Illuminate\Http\Response */ public function handleFacebookCallback(Request $request) { $socialite = $this->setSocialiteConfigs(); $facebookUser = $socialite->driver('facebook')->user(); return $this->processSocialMediaLogin($request, 'facebook_id', $facebookUser); } /** * Obtain the user information from Twitter. * * @return \Illuminate\Http\Response */ public function handleTwitterCallback(Request $request) { $socialite = $this->setSocialiteConfigs(); $twitterUser = $socialite->driver('twitter')->user(); return $this->processSocialMediaLogin($request, 'twitter_id', $twitterUser); } private function processSocialMediaLogin(Request $request, $socialMediaIdField, $socialMediaUser) { $userBySocialMediaId = User::where($socialMediaIdField, $socialMediaUser->getId())->first(); if (!is_null($userBySocialMediaId)) { // We have an existing user for this Facebook ID - log them in $this->guard()->login($userBySocialMediaId); return redirect(route('home')); } // Some providers (*cough*Twitter*cough*) don't give e-mail addresses without explicit permission/additional // verification if (!is_null($socialMediaUser->email)) { $userByEmailAddress = User::where('email', $socialMediaUser->getEmail())->first(); if (!is_null($userByEmailAddress)) { // We have an existing user with the e-mail address associated with the Facebook account // Prompt for the password for that account $request->getSession()->put('ssoLoginData', [ 'name' => $socialMediaUser->getName(), 'email' => $socialMediaUser->getEmail(), $socialMediaIdField => $socialMediaUser->getId(), 'is_activated' => true ]); return redirect(route('auth.login_sso')); } } // We don't have an existing user - prompt for registration $request->getSession()->put('ssoRegisterData', [ 'name' => $socialMediaUser->getName(), 'email' => $socialMediaUser->getEmail(), $socialMediaIdField => $socialMediaUser->getId(), 'is_activated' => true ]); return redirect(route('auth.register_sso')); } private function setSocialiteConfigs() { // Force Socialite to use our config from the database instead of hard-coded in config/services.php $socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class); $socialite->extend( 'facebook', function ($app) use ($socialite) { $config = [ 'client_id' => UserConfig::get('facebook_app_id'), 'client_secret' => decrypt(UserConfig::get('facebook_app_secret')), 'redirect' => route('login_callback.facebook') ]; return $socialite->buildProvider(FacebookProvider::class, $config); } ); $socialite->extend( 'twitter', function ($app) use ($socialite) { $config = [ 'identifier' => UserConfig::get('twitter_app_id'), 'secret' => decrypt(UserConfig::get('twitter_app_secret')), 'callback_uri' => route('login_callback.twitter') ]; return new TwitterProvider($app['request'], new TwitterServer($config)); } ); return $socialite; } }