blue-twilight/app/Http/Controllers/Auth/LoginController.php

391 lines
11 KiB
PHP
Raw Permalink Normal View History

<?php
namespace App\Http\Controllers\Auth;
use App\ExternalService;
use App\Facade\Theme;
use App\Facade\UserConfig;
use App\Helpers\MiscHelper;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Contracts\Routing\UrlGenerator;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Laravel\Socialite\One\TwitterProvider;
use Laravel\Socialite\Two\FacebookProvider;
use Laravel\Socialite\Two\GoogleProvider;
use League\OAuth1\Client\Server\Twitter as TwitterServer;
use Socialite;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* @var UrlGenerator
*/
protected $generator;
/**
* Where to redirect users after login / registration.
*
* @var string
*/
protected $redirectTo = '/me';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct(UrlGenerator $generator)
{
$this->middleware('guest', ['except' => 'logout']);
$this->generator = $generator;
}
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->invalidate();
return redirect()->back();
}
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)
{
$previousUrl = MiscHelper::ensureHasTrailingSlash($this->generator->previous(false));
$homeUrl = MiscHelper::ensureHasTrailingSlash(route('home'));
if (UserConfig::get('social_user_feeds') && (empty($previousUrl) || $previousUrl == $homeUrl))
{
$previousUrl = route('userActivityFeed');
}
$request->getSession()->put('url.intended', $previousUrl);
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->setSocialiteConfigForFacebook();
if (is_null($socialite))
{
return redirect(route('login'));
}
return $socialite->driver('facebook')->redirect();
}
/**
* Redirect the user to the Google authentication page.
*
* @return \Illuminate\Http\Response
*/
public function redirectToGoogle()
{
$socialite = $this->setSocialiteConfigForGoogle();
if (is_null($socialite))
{
return redirect(route('login'));
}
return $socialite->driver('google')->redirect();
}
/**
* Redirect the user to the Twitter authentication page.
*
* @return \Illuminate\Http\Response
*/
public function redirectToTwitter()
{
$socialite = $this->setSocialiteConfigForTwitter();
if (is_null($socialite))
{
return redirect(route('login'));
}
return $socialite->driver('twitter')->redirect();
}
/**
* Obtain the user information from Facebook.
*
* @return \Illuminate\Http\Response
*/
public function handleFacebookCallback(Request $request)
{
$socialite = $this->setSocialiteConfigForFacebook();
if (is_null($socialite))
{
return redirect(route('login'));
}
$facebookUser = $socialite->driver('facebook')->user();
return $this->processSocialMediaLogin($request, 'facebook_id', $facebookUser);
}
/**
* Obtain the user information from Google.
*
* @return \Illuminate\Http\Response
*/
public function handleGoogleCallback(Request $request)
{
$socialite = $this->setSocialiteConfigForGoogle();
if (is_null($socialite))
{
return redirect(route('login'));
}
$googleUser = $socialite->driver('google')->user();
return $this->processSocialMediaLogin($request, 'google_id', $googleUser);
}
/**
* Obtain the user information from Twitter.
*
* @return \Illuminate\Http\Response
*/
public function handleTwitterCallback(Request $request)
{
$socialite = $this->setSocialiteConfigForTwitter();
if (is_null($socialite))
{
return redirect(route('login'));
}
$twitterUser = $socialite->driver('twitter')->user();
return $this->processSocialMediaLogin($request, 'twitter_id', $twitterUser);
}
private function getSocialMediaConfig($socialMediaEnabledField, $socialMediaExternalServiceIdField)
{
if (boolval(UserConfig::get($socialMediaEnabledField)))
{
$externalServiceID = intval(UserConfig::get($socialMediaExternalServiceIdField));
$externalService = ExternalService::where('id', $externalServiceID)->first();
return $externalService;
}
return null;
}
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 setSocialiteConfigForFacebook()
{
$facebookConfig = $this->getSocialMediaConfig(
'social_facebook_login',
'facebook_external_service_id'
);
if (is_null($facebookConfig))
{
return null;
}
$socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class);
$socialite->extend(
'facebook',
function ($app) use ($socialite, $facebookConfig) {
$config = [
'client_id' => trim(decrypt($facebookConfig->app_id)),
'client_secret' => trim(decrypt($facebookConfig->app_secret)),
'redirect' => route('login_callback.facebook')
];
return $socialite->buildProvider(FacebookProvider::class, $config);
}
);
return $socialite;
}
private function setSocialiteConfigForGoogle()
{
$googleConfig = $this->getSocialMediaConfig(
'social_google_login',
'google_external_service_id'
);
if (is_null($googleConfig))
{
return null;
}
$socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class);
$socialite->extend(
'google',
function ($app) use ($socialite, $googleConfig) {
$config = [
'client_id' => trim(decrypt($googleConfig->app_id)),
'client_secret' => trim(decrypt($googleConfig->app_secret)),
'redirect' => route('login_callback.google')
];
return $socialite->buildProvider(GoogleProvider::class, $config);
}
);
return $socialite;
}
private function setSocialiteConfigForTwitter()
{
$twitterConfig = $this->getSocialMediaConfig(
'social_twitter_login',
'twitter_external_service_id'
);
if (is_null($twitterConfig))
{
return null;
}
$socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class);
$socialite->extend(
'twitter',
function ($app) use ($socialite, $twitterConfig) {
$config = [
'identifier' => trim(decrypt($twitterConfig->app_id)),
'secret' => trim(decrypt($twitterConfig->app_secret)),
'callback_uri' => route('login_callback.twitter')
];
return new TwitterProvider($app['request'], new TwitterServer($config));
}
);
return $socialite;
}
}