From 564fcd4b093547b29363731f55d2e41973dd4332 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Mon, 13 Aug 2018 14:25:56 +0100 Subject: [PATCH 1/8] #5: Added Laravel Socialite. The redirect to Facebook is now working. --- app/Http/Controllers/Auth/LoginController.php | 24 ++++ composer.json | 3 +- composer.lock | 127 +++++++++++++++++- config/services.php | 6 + routes/web.php | 4 + 5 files changed, 162 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 30fdda1..1161dd6 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -6,6 +6,7 @@ use App\Facade\Theme; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; +use Socialite; class LoginController extends Controller { @@ -61,4 +62,27 @@ class LoginController extends Controller 'info' => $request->session()->get('info') ]); } + + /** + * Redirect the user to the Facebook authentication page. + * + * @return \Illuminate\Http\Response + */ + public function redirectToFacebook() + { + return Socialite::driver('facebook')->redirect(); + } + + /** + * Obtain the user information from Facebook. + * + * @return \Illuminate\Http\Response + */ + public function handleFacebookCallback() + { + $user = Socialite::driver('facebook')->user(); + dd($user); + + // $user->token; + } } diff --git a/composer.json b/composer.json index c594bea..32bb1db 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,8 @@ "laravel/framework": "5.5.*", "rackspace/php-opencloud": "^1.16", "doctrine/dbal": "^2.5", - "aws/aws-sdk-php": "^3.19" + "aws/aws-sdk-php": "^3.19", + "laravel/socialite": "^3.0" }, "require-dev": { "filp/whoops": "~2.0", diff --git a/composer.lock b/composer.lock index ca1bee2..4497bb3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2469338aa47d9194dc0c44bc788fb070", + "content-hash": "7e1113109ae57d549a01afba28bdb219", "packages": [ { "name": "aws/aws-sdk-php", @@ -948,6 +948,68 @@ ], "time": "2018-03-30T13:29:30+00:00" }, + { + "name": "laravel/socialite", + "version": "v3.0.12", + "source": { + "type": "git", + "url": "https://github.com/laravel/socialite.git", + "reference": "b5f465847b1d637efa86bbfe2fc1c9d2bd12f60f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/socialite/zipball/b5f465847b1d637efa86bbfe2fc1c9d2bd12f60f", + "reference": "b5f465847b1d637efa86bbfe2fc1c9d2bd12f60f", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~6.0", + "illuminate/contracts": "~5.4", + "illuminate/http": "~5.4", + "illuminate/support": "~5.4", + "league/oauth1-client": "~1.0", + "php": ">=5.4.0" + }, + "require-dev": { + "mockery/mockery": "~0.9", + "phpunit/phpunit": "~4.0|~5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Socialite\\SocialiteServiceProvider" + ], + "aliases": { + "Socialite": "Laravel\\Socialite\\Facades\\Socialite" + } + } + }, + "autoload": { + "psr-4": { + "Laravel\\Socialite\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.", + "keywords": [ + "laravel", + "oauth" + ], + "time": "2018-06-01T15:06:47+00:00" + }, { "name": "league/flysystem", "version": "1.0.45", @@ -1032,6 +1094,69 @@ ], "time": "2018-05-07T08:44:23+00:00" }, + { + "name": "league/oauth1-client", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth1-client.git", + "reference": "fca5f160650cb74d23fc11aa570dd61f86dcf647" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/fca5f160650cb74d23fc11aa570dd61f86dcf647", + "reference": "fca5f160650cb74d23fc11aa570dd61f86dcf647", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0" + }, + "require-dev": { + "mockery/mockery": "^0.9", + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth1\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Corlett", + "email": "bencorlett@me.com", + "homepage": "http://www.webcomm.com.au", + "role": "Developer" + } + ], + "description": "OAuth 1.0 Client Library", + "keywords": [ + "Authentication", + "SSO", + "authorization", + "bitbucket", + "identity", + "idp", + "oauth", + "oauth1", + "single sign on", + "trello", + "tumblr", + "twitter" + ], + "time": "2016-08-17T00:36:58+00:00" + }, { "name": "mikemccabe/json-patch-php", "version": "0.1.0", diff --git a/config/services.php b/config/services.php index eab4683..b7c6039 100644 --- a/config/services.php +++ b/config/services.php @@ -14,6 +14,12 @@ return [ | */ + 'facebook' => [ + 'client_id' => env('FACEBOOK_CLIENT_ID'), + 'client_secret' => env('FACEBOOK_CLIENT_SECRET'), + 'redirect' => url('login/facebook/callback') + ], + 'gitea' => [ 'api_url' => 'https://apps.andysh.uk/api/v1', 'cache_time_seconds' => 3600, diff --git a/routes/web.php b/routes/web.php index f0357fe..1110f8d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -74,6 +74,10 @@ Route::group(['prefix' => 'install'], function () { Route::post('/database', 'InstallController@database')->name('install.database'); }); +// Social media SSO +Route::get('login/facebook', 'Auth\LoginController@redirectToFacebook')->name('login.facebook'); +Route::get('login/facebook/callback', 'Auth\LoginController@handleFacebookCallback')->name('login_callback.facebook'); + // Gallery Route::get('/', 'Gallery\DefaultController@index')->name('home'); Route::get('/activate/{token}', 'Auth\ActivateController@activate')->name('auth.activate'); From 52473f846eb63389ec66c7b2a04cc8ac77a73b44 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Mon, 13 Aug 2018 22:03:12 +0100 Subject: [PATCH 2/8] #5: Facebook social login now works. Added Facebook to the login screen template (I'm not 100% happy with this, may need a bit more work.) --- app/Http/Controllers/Auth/LoginController.php | 23 ++++++-- .../Controllers/Auth/RegisterController.php | 53 ++++++++++++------- app/User.php | 2 +- config/services.php | 2 +- ..._13_211541_add_user_facebook_id_column.php | 34 ++++++++++++ resources/lang/en/auth.php | 6 ++- .../themes/base/partials/login.blade.php | 8 +++ .../themes/base/partials/register.blade.php | 14 +++-- 8 files changed, 113 insertions(+), 29 deletions(-) create mode 100644 database/migrations/2018_08_13_211541_add_user_facebook_id_column.php diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 1161dd6..770afc3 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Auth; use App\Facade\Theme; use App\Http\Controllers\Controller; +use App\User; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; use Socialite; @@ -78,11 +79,25 @@ class LoginController extends Controller * * @return \Illuminate\Http\Response */ - public function handleFacebookCallback() + public function handleFacebookCallback(Request $request) { - $user = Socialite::driver('facebook')->user(); - dd($user); + $facebookUser = Socialite::driver('facebook')->user(); + $user = User::where('facebook_id', $facebookUser->id)->first(); - // $user->token; + if (is_null($user)) + { + $request->getSession()->put('registerData', [ + 'name' => $facebookUser->name, + 'email' => $facebookUser->email, + 'facebook_id' => $facebookUser->id, + 'is_activated' => true + ]); + + return redirect(route('register')); + } + + $this->guard()->login($user); + + return redirect(route('home')); } } diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index 7dd3d60..932765d 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -85,25 +85,22 @@ class RegisterController extends Controller */ protected function create(array $data) { - $activationData = [ - 'is_activated' => true - ]; - - if (UserConfig::get('require_email_verification')) + if (!isset($data['is_activated'])) { - $activationData['is_activated'] = false; - $activationData['activation_token'] = MiscHelper::randomString(); + $data['is_activated'] = true; + + if (UserConfig::get('require_email_verification')) + { + $data['is_activated'] = false; + $data['activation_token'] = MiscHelper::randomString(); + } } - return User::create(array_merge( - [ - 'name' => $data['name'], - 'email' => $data['email'], - 'password' => bcrypt($data['password']), - 'is_admin' => false - ], - $activationData - )); + $data['password'] = bcrypt($data['password']); + $data['is_admin'] = false; + unset($data['password_confirmation']); + + return User::create($data); } public function register(Request $request) @@ -115,8 +112,17 @@ class RegisterController extends Controller $this->validator($request)->validate(); + $userData = $request->all(); + + // Social media login info + $registerData = $request->getSession()->get('registerData'); + if (!is_null($registerData)) + { + $userData = array_merge($registerData, $userData); + } + /** @var User $user */ - $user = $this->create($request->all()); + $user = $this->create($userData); if ($user->is_activated) { @@ -137,15 +143,24 @@ class RegisterController extends Controller * * @return \Illuminate\Http\Response */ - public function showRegistrationForm() + public function showRegistrationForm(Request $request) { if (!UserConfig::get('allow_self_registration')) { return redirect(route('home')); } + // Social media login info + $registerData = $request->getSession()->get('registerData'); + if (is_null($registerData)) + { + $registerData['name'] = ''; + $registerData['email'] = ''; + } + return Theme::render('auth.v2_unified', [ - 'active_tab' => 'register' + 'active_tab' => 'register', + 'register_data' => $registerData ]); } } diff --git a/app/User.php b/app/User.php index 6cf4a92..72f3a42 100644 --- a/app/User.php +++ b/app/User.php @@ -16,7 +16,7 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'name', 'email', 'password', 'is_admin', 'is_activated', 'activation_token', 'profile_alias' + 'name', 'email', 'password', 'is_admin', 'is_activated', 'activation_token', 'enable_profile_page', 'profile_alias', 'facebook_id' ]; /** diff --git a/config/services.php b/config/services.php index b7c6039..a99b3fb 100644 --- a/config/services.php +++ b/config/services.php @@ -17,7 +17,7 @@ return [ 'facebook' => [ 'client_id' => env('FACEBOOK_CLIENT_ID'), 'client_secret' => env('FACEBOOK_CLIENT_SECRET'), - 'redirect' => url('login/facebook/callback') + 'redirect' => php_sapi_name() != 'cli' ? url('login/facebook/callback') : '' ], 'gitea' => [ diff --git a/database/migrations/2018_08_13_211541_add_user_facebook_id_column.php b/database/migrations/2018_08_13_211541_add_user_facebook_id_column.php new file mode 100644 index 0000000..685d15f --- /dev/null +++ b/database/migrations/2018_08_13_211541_add_user_facebook_id_column.php @@ -0,0 +1,34 @@ +string('facebook_id')->nullable(true); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) + { + $table->dropColumn('facebook_id'); + }); + } +} diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php index 5a61ca2..172bd1a 100644 --- a/resources/lang/en/auth.php +++ b/resources/lang/en/auth.php @@ -22,6 +22,8 @@ return [ 'Please click the link in this e-mail to activate your account.', 'change_password_action' => 'Change password', 'change_password_title' => 'Change your password', + 'email_password_login' => 'Alternatively, login with your e-mail address and password:', + 'email_password_register' => 'Alternatively, create an account using your e-mail address and a password:', 'forgot_password_action' => 'Send Reset E-mail', 'forgot_password_link' => 'Forgotten your password?', 'forgot_password_title' => 'Send password reset link', @@ -29,5 +31,7 @@ return [ 'recaptcha_failed_message' => 'The reCAPTCHA verfication failed. Please ensure you have completed the reCAPTCHA challenge and try again.', 'register_page_title' => 'Create an account', 'reset_password_action' => 'Reset Password', - 'reset_password_title' => 'Reset your password' + 'reset_password_title' => 'Reset your password', + 'social_login' => 'Feeling sociable? Login with:', + 'social_register' => 'Feeling sociable? Register with:' ]; diff --git a/resources/views/themes/base/partials/login.blade.php b/resources/views/themes/base/partials/login.blade.php index bc7c194..e61c2aa 100644 --- a/resources/views/themes/base/partials/login.blade.php +++ b/resources/views/themes/base/partials/login.blade.php @@ -1,3 +1,11 @@ +

@lang('auth.social_login')

+

+ + {{----}} +

+ +

@lang('auth.email_password_login')

+
{{ csrf_field() }} diff --git a/resources/views/themes/base/partials/register.blade.php b/resources/views/themes/base/partials/register.blade.php index a2198f4..ac55fc4 100644 --- a/resources/views/themes/base/partials/register.blade.php +++ b/resources/views/themes/base/partials/register.blade.php @@ -1,3 +1,11 @@ +

@lang('auth.social_register')

+

+ + {{----}} +

+ +

@lang('auth.email_password_register')

+ {{ csrf_field() }} @@ -5,7 +13,7 @@
- + @if ($errors->has('name'))
@@ -19,7 +27,7 @@
- + @if ($errors->has('email'))
@@ -33,7 +41,7 @@
- + @if ($errors->has('password'))
From 8af88c56aa5909fd444e0a1e419ef0c6719a6b2f Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Tue, 14 Aug 2018 09:12:28 +0100 Subject: [PATCH 3/8] #5: Added settings UI to configure Facebook login --- app/Helpers/ConfigHelper.php | 3 ++ .../Controllers/Admin/DefaultController.php | 3 ++ resources/lang/en/admin.php | 1 + resources/lang/en/forms.php | 4 ++ .../themes/base/admin/settings.blade.php | 46 +++++++++++++++++++ 5 files changed, 57 insertions(+) diff --git a/app/Helpers/ConfigHelper.php b/app/Helpers/ConfigHelper.php index c1579b4..be02b83 100644 --- a/app/Helpers/ConfigHelper.php +++ b/app/Helpers/ConfigHelper.php @@ -104,6 +104,8 @@ class ConfigHelper 'date_format' => $this->allowedDateFormats()[0], 'default_album_view' => $this->allowedAlbumViews()[0], 'enable_visitor_hits' => false, + 'facebook_app_id' => '', + 'facebook_app_secret' => '', 'hotlink_protection' => false, 'items_per_page' => 12, 'items_per_page_admin' => 10, @@ -120,6 +122,7 @@ class ConfigHelper 'smtp_password' => '', 'smtp_port' => 25, 'smtp_username' => '', + 'social_facebook_login' => false, 'social_user_profiles' => false, 'theme' => 'default' ); diff --git a/app/Http/Controllers/Admin/DefaultController.php b/app/Http/Controllers/Admin/DefaultController.php index 815de1b..68fdd3a 100644 --- a/app/Http/Controllers/Admin/DefaultController.php +++ b/app/Http/Controllers/Admin/DefaultController.php @@ -224,12 +224,15 @@ class DefaultController extends Controller 'require_email_verification', 'restrict_original_download', 'smtp_encryption', + 'social_facebook_login', 'social_user_profiles' ]; $updateKeys = [ 'albums_menu_number_items', 'app_name', 'date_format', + 'facebook_app_id', + 'facebook_app_secret', 'sender_address', 'sender_name', 'smtp_server', diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php index 665f129..a828ceb 100644 --- a/resources/lang/en/admin.php +++ b/resources/lang/en/admin.php @@ -211,6 +211,7 @@ return [ 'analytics_tab' => 'Analytics', 'security_allow_self_registration' => 'Allow self-registration', 'security_allow_self_registration_description' => 'With this option enabled, users can sign up for their own accounts. You can grant permissions to accounts to allow users to upload their own photos or manage yours.', + 'social_facebook' => 'Facebook', 'social_tab' => 'Social' ], 'select_all_action' => 'Select all', diff --git a/resources/lang/en/forms.php b/resources/lang/en/forms.php index eaabb28..09808d8 100644 --- a/resources/lang/en/forms.php +++ b/resources/lang/en/forms.php @@ -45,6 +45,10 @@ return [ 'settings_hotlink_protection_help' => 'With this option enabled, direct linking to images is not allowed. Photos can only be viewed through Blue Twilight.', 'settings_restrict_originals_download' => 'Restrict access to original images', 'settings_restrict_originals_download_help' => 'With this option enabled, only the photo\'s owner can download the original high-resolution images.', + 'settings_social_facebook_app_id' => 'Facebook App ID:', + 'settings_social_facebook_app_secret' => 'Facebook App Secret:', + 'settings_social_facebook_login' => 'Allow login/registration with a Facebook account.', + 'settings_social_facebook_login_help' => 'With this option enabled, users can register (if enabled) and login with their Facebook account.', 'settings_social_user_profiles' => 'Enable public user profiles', 'settings_social_user_profiles_help' => 'Display public pages for users showing their albums, cameras used and activity.', 'storage_access_key_label' => 'Access key:', diff --git a/resources/views/themes/base/admin/settings.blade.php b/resources/views/themes/base/admin/settings.blade.php index faab460..4710d11 100644 --- a/resources/views/themes/base/admin/settings.blade.php +++ b/resources/views/themes/base/admin/settings.blade.php @@ -324,6 +324,52 @@ @lang('forms.settings_social_user_profiles_help')
+ +
+ +
+
+ +
+ +
+
+ + @lang('admin.settings.social_facebook') + + +
+ + +
+ +
+ + + + @if ($errors->has('facebook_app_id')) +
+ {{ $errors->first('facebook_app_id') }} +
+ @endif +
+ +
+ + + + @if ($errors->has('facebook_app_secret')) +
+ {{ $errors->first('facebook_app_secret') }} +
+ @endif +
+
+
+
From 40fc25eba904c93789f8c856665fac96da862ee7 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Tue, 14 Aug 2018 12:57:41 +0100 Subject: [PATCH 4/8] #5: Facebook login is now working using the app ID/secret stored in the database, instead of in the services file --- .../Controllers/Admin/DefaultController.php | 20 +++++++++++--- app/Http/Controllers/Auth/LoginController.php | 27 +++++++++++++++++-- config/services.php | 6 ----- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/Admin/DefaultController.php b/app/Http/Controllers/Admin/DefaultController.php index 68fdd3a..5dd439c 100644 --- a/app/Http/Controllers/Admin/DefaultController.php +++ b/app/Http/Controllers/Admin/DefaultController.php @@ -29,10 +29,17 @@ use Illuminate\Support\Facades\View; class DefaultController extends Controller { + private $passwordSettingKeys; + public function __construct() { $this->middleware('auth'); View::share('is_admin', true); + + $this->passwordSettingKeys = [ + 'smtp_password', + 'facebook_app_secret' + ]; } public function about() @@ -211,9 +218,6 @@ class DefaultController extends Controller { $this->authorizeAccessToAdminPanel('admin:configure'); - $passwordKeys = [ - 'smtp_password' - ]; $checkboxKeys = [ 'albums_menu_parents_only', 'allow_self_registration', @@ -264,7 +268,7 @@ class DefaultController extends Controller } $config->value = $request->request->get($key); - if (in_array($key, $passwordKeys) && strlen($config->value) > 0) + if (in_array($key, $this->passwordSettingKeys) && strlen($config->value) > 0) { $config->value = encrypt($config->value); } @@ -313,6 +317,14 @@ class DefaultController extends Controller $dateFormatsLookup[$dateFormat] = date($dateFormat); } + foreach ($this->passwordSettingKeys as $passwordSettingKey) + { + if (isset($config[$passwordSettingKey]) && !empty($config[$passwordSettingKey])) + { + $config[$passwordSettingKey] = decrypt($config[$passwordSettingKey]); + } + } + $themeNamesLookup = UserConfig::allowedThemeNames(); return Theme::render('admin.settings', [ diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 770afc3..715e3fb 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -3,10 +3,12 @@ namespace App\Http\Controllers\Auth; use App\Facade\Theme; +use App\Facade\UserConfig; use App\Http\Controllers\Controller; use App\User; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; +use Laravel\Socialite\Two\FacebookProvider; use Socialite; class LoginController extends Controller @@ -71,7 +73,8 @@ class LoginController extends Controller */ public function redirectToFacebook() { - return Socialite::driver('facebook')->redirect(); + $socialite = $this->setSocialiteConfigs(); + return $socialite->driver('facebook')->redirect(); } /** @@ -81,7 +84,8 @@ class LoginController extends Controller */ public function handleFacebookCallback(Request $request) { - $facebookUser = Socialite::driver('facebook')->user(); + $socialite = $this->setSocialiteConfigs(); + $facebookUser = $socialite->driver('facebook')->user(); $user = User::where('facebook_id', $facebookUser->id)->first(); if (is_null($user)) @@ -100,4 +104,23 @@ class LoginController extends Controller return redirect(route('home')); } + + 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'); + $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); + } + ); + + return $socialite; + } } diff --git a/config/services.php b/config/services.php index a99b3fb..eab4683 100644 --- a/config/services.php +++ b/config/services.php @@ -14,12 +14,6 @@ return [ | */ - 'facebook' => [ - 'client_id' => env('FACEBOOK_CLIENT_ID'), - 'client_secret' => env('FACEBOOK_CLIENT_SECRET'), - 'redirect' => php_sapi_name() != 'cli' ? url('login/facebook/callback') : '' - ], - 'gitea' => [ 'api_url' => 'https://apps.andysh.uk/api/v1', 'cache_time_seconds' => 3600, From 8290bafb0479f7c3b934731d206829cb7ef76ef2 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Wed, 15 Aug 2018 14:22:13 +0100 Subject: [PATCH 5/8] #5: It's now possible to sign in/register with a Facebook account, and to link the FB account to an existing account by entering the account's password. --- app/Http/Controllers/Auth/LoginController.php | 94 ++++++++++++++++--- .../Controllers/Auth/RegisterController.php | 28 +++++- resources/lang/en/auth.php | 3 + .../themes/base/auth/v2_unified.blade.php | 22 ++++- .../themes/base/partials/login.blade.php | 43 +++++---- .../themes/base/partials/register.blade.php | 26 +++-- routes/web.php | 2 + 7 files changed, 173 insertions(+), 45 deletions(-) diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 715e3fb..88cd5f1 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -43,6 +43,31 @@ class LoginController extends Controller $this->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'); @@ -62,7 +87,31 @@ class LoginController extends Controller { return Theme::render('auth.v2_unified', [ 'active_tab' => 'login', - 'info' => $request->session()->get('info') + '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 ]); } @@ -86,29 +135,52 @@ class LoginController extends Controller { $socialite = $this->setSocialiteConfigs(); $facebookUser = $socialite->driver('facebook')->user(); - $user = User::where('facebook_id', $facebookUser->id)->first(); - if (is_null($user)) + return $this->processSocialMediaLogin($request, 'facebook_id', $facebookUser); + } + + private function processSocialMediaLogin(Request $request, $socialMediaIdField, $socialMediaUser) + { + $userBySocialMediaId = User::where($socialMediaIdField, $socialMediaUser->getId())->first(); + + if (!is_null($userBySocialMediaId)) { - $request->getSession()->put('registerData', [ - 'name' => $facebookUser->name, - 'email' => $facebookUser->email, - 'facebook_id' => $facebookUser->id, + // We have an existing user for this Facebook ID - log them in + $this->guard()->login($userBySocialMediaId); + return redirect(route('home')); + } + + $userByEmailAddress = User::where('email', $socialMediaUser->email)->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('register')); + return redirect(route('auth.login_sso')); } - $this->guard()->login($user); + // 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('home')); + 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'); + $socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class); $socialite->extend( 'facebook', function ($app) use ($socialite) { diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index 932765d..1155fa7 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -115,10 +115,11 @@ class RegisterController extends Controller $userData = $request->all(); // Social media login info - $registerData = $request->getSession()->get('registerData'); + $registerData = $request->getSession()->get('ssoRegisterData'); if (!is_null($registerData)) { $userData = array_merge($registerData, $userData); + $request->getSession()->remove('ssoRegisterData'); } /** @var User $user */ @@ -150,16 +151,35 @@ class RegisterController extends Controller return redirect(route('home')); } + return Theme::render('auth.v2_unified', [ + 'active_tab' => 'register', + 'is_sso' => false + ]); + } + + /** + * Show the application registration form (for a social media-linked account). + * + * @return \Illuminate\Http\Response + */ + public function showRegistrationFormSso(Request $request) + { + if (!UserConfig::get('allow_self_registration')) + { + return redirect(route('home')); + } + // Social media login info - $registerData = $request->getSession()->get('registerData'); + $registerData = $request->getSession()->get('ssoRegisterData'); if (is_null($registerData)) { - $registerData['name'] = ''; - $registerData['email'] = ''; + // No SSO data in session, use the normal registration screen + return redirect(route('register')); } return Theme::render('auth.v2_unified', [ 'active_tab' => 'register', + 'is_sso' => true, 'register_data' => $registerData ]); } diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php index 172bd1a..545f1b6 100644 --- a/resources/lang/en/auth.php +++ b/resources/lang/en/auth.php @@ -23,7 +23,10 @@ return [ 'change_password_action' => 'Change password', 'change_password_title' => 'Change your password', 'email_password_login' => 'Alternatively, login with your e-mail address and password:', + 'email_password_login_sso' => 'The social media account you logged in with has not been used here before, however an account with the e-mail address already exists.', + 'email_password_login_sso_2' => 'Please enter the password for this account to link your social media account to it.', 'email_password_register' => 'Alternatively, create an account using your e-mail address and a password:', + 'email_password_register_sso' => 'Please confirm your name and set a password for your account:', 'forgot_password_action' => 'Send Reset E-mail', 'forgot_password_link' => 'Forgotten your password?', 'forgot_password_title' => 'Send password reset link', diff --git a/resources/views/themes/base/auth/v2_unified.blade.php b/resources/views/themes/base/auth/v2_unified.blade.php index f1d7f24..200d7f3 100644 --- a/resources/views/themes/base/auth/v2_unified.blade.php +++ b/resources/views/themes/base/auth/v2_unified.blade.php @@ -8,13 +8,25 @@
diff --git a/resources/views/themes/base/partials/login.blade.php b/resources/views/themes/base/partials/login.blade.php index e61c2aa..3fd6848 100644 --- a/resources/views/themes/base/partials/login.blade.php +++ b/resources/views/themes/base/partials/login.blade.php @@ -1,10 +1,14 @@ -

@lang('auth.social_login')

-

- - {{----}} -

+@if (!$is_sso) +

@lang('auth.social_login')

+

+ +

-

@lang('auth.email_password_login')

+

@lang('auth.email_password_login')

+@else +

@lang('auth.email_password_login_sso')

+

@lang('auth.email_password_login_sso_2')

+@endif {{ csrf_field() }} @@ -13,7 +17,12 @@
- + @if ($is_sso) + + + @else + + @endif @if ($errors->has('email'))
@@ -27,7 +36,7 @@
- + @if ($errors->has('password'))
@@ -37,16 +46,18 @@
-
-
-
-
- - + @if (!$is_sso) +
+
+
+
+ + +
-
+ @endif
diff --git a/resources/views/themes/base/partials/register.blade.php b/resources/views/themes/base/partials/register.blade.php index ac55fc4..7c6e3cc 100644 --- a/resources/views/themes/base/partials/register.blade.php +++ b/resources/views/themes/base/partials/register.blade.php @@ -1,10 +1,13 @@ -

@lang('auth.social_register')

-

- - {{----}} -

+@if (!$is_sso) +

@lang('auth.social_register')

+

+ +

-

@lang('auth.email_password_register')

+

@lang('auth.email_password_register')

+@else +

@lang('auth.email_password_register_sso')

+@endif {{ csrf_field() }} @@ -13,7 +16,7 @@
- + @if ($errors->has('name'))
@@ -27,7 +30,12 @@
- + @if ($is_sso) + + + @else + + @endif @if ($errors->has('email'))
@@ -41,7 +49,7 @@
- + @if ($errors->has('password'))
diff --git a/routes/web.php b/routes/web.php index 1110f8d..3521f5a 100644 --- a/routes/web.php +++ b/routes/web.php @@ -77,6 +77,8 @@ Route::group(['prefix' => 'install'], function () { // Social media SSO Route::get('login/facebook', 'Auth\LoginController@redirectToFacebook')->name('login.facebook'); Route::get('login/facebook/callback', 'Auth\LoginController@handleFacebookCallback')->name('login_callback.facebook'); +Route::get('login/sso', 'Auth\LoginController@showLoginFormSso')->name('auth.login_sso'); +Route::get('register/sso', 'Auth\RegisterController@showRegistrationFormSso')->name('auth.register_sso'); // Gallery Route::get('/', 'Gallery\DefaultController@index')->name('home'); From 1ed4f297d2ae2a200172bbccd68272f13d4332a0 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Thu, 16 Aug 2018 09:18:54 +0100 Subject: [PATCH 6/8] #5: Added settings for configuring Twitter login, this is getting as far now as presenting the Twitter login screen. Login/register screens now respect the social media provider settings --- app/Helpers/ConfigHelper.php | 11 +++- .../Controllers/Admin/DefaultController.php | 6 ++- app/Http/Controllers/Auth/LoginController.php | 24 +++++++++ resources/lang/en/admin.php | 3 +- resources/lang/en/forms.php | 4 ++ .../themes/base/admin/settings.blade.php | 52 ++++++++++++++++++- .../themes/base/partials/login.blade.php | 8 +-- .../themes/base/partials/register.blade.php | 8 +-- .../partials/social_login_providers.blade.php | 8 +++ routes/web.php | 2 + 10 files changed, 113 insertions(+), 13 deletions(-) create mode 100644 resources/views/themes/base/partials/social_login_providers.blade.php diff --git a/app/Helpers/ConfigHelper.php b/app/Helpers/ConfigHelper.php index be02b83..b2ee231 100644 --- a/app/Helpers/ConfigHelper.php +++ b/app/Helpers/ConfigHelper.php @@ -123,8 +123,11 @@ class ConfigHelper 'smtp_port' => 25, 'smtp_username' => '', 'social_facebook_login' => false, + 'social_twitter_login' => false, 'social_user_profiles' => false, - 'theme' => 'default' + 'theme' => 'default', + 'twitter_app_id' => '', + 'twitter_app_secret' => '', ); } @@ -171,4 +174,10 @@ class ConfigHelper return $config; } + + public function isSocialMediaLoginEnabled() + { + return $this->get('social_facebook_login') || + $this->get('social_twitter_login'); + } } \ No newline at end of file diff --git a/app/Http/Controllers/Admin/DefaultController.php b/app/Http/Controllers/Admin/DefaultController.php index 5dd439c..8553d1c 100644 --- a/app/Http/Controllers/Admin/DefaultController.php +++ b/app/Http/Controllers/Admin/DefaultController.php @@ -38,7 +38,8 @@ class DefaultController extends Controller $this->passwordSettingKeys = [ 'smtp_password', - 'facebook_app_secret' + 'facebook_app_secret', + 'twitter_app_secret' ]; } @@ -229,6 +230,7 @@ class DefaultController extends Controller 'restrict_original_download', 'smtp_encryption', 'social_facebook_login', + 'social_twitter_login', 'social_user_profiles' ]; $updateKeys = [ @@ -244,6 +246,8 @@ class DefaultController extends Controller 'smtp_username', 'smtp_password', 'theme', + 'twitter_app_id', + 'twitter_app_secret', 'recaptcha_site_key', 'recaptcha_secret_key', 'analytics_code' diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 88cd5f1..177a782 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -8,7 +8,9 @@ use App\Http\Controllers\Controller; use App\User; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; +use Laravel\Socialite\One\TwitterProvider; use Laravel\Socialite\Two\FacebookProvider; +use League\OAuth1\Client\Server\Twitter as TwitterServer; use Socialite; class LoginController extends Controller @@ -126,6 +128,17 @@ class LoginController extends Controller 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. * @@ -192,6 +205,17 @@ class LoginController extends Controller 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; } diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php index 922cc10..83e362a 100644 --- a/resources/lang/en/admin.php +++ b/resources/lang/en/admin.php @@ -212,7 +212,8 @@ return [ 'security_allow_self_registration' => 'Allow self-registration', 'security_allow_self_registration_description' => 'With this option enabled, users can sign up for their own accounts. You can grant permissions to accounts to allow users to upload their own photos or manage yours.', 'social_facebook' => 'Facebook', - 'social_tab' => 'Social' + 'social_tab' => 'Social', + 'social_twitter' => 'Twitter' ], 'select_all_action' => 'Select all', 'select_all_album_active' => 'Any action you select in the list below will apply to all photos in this album.', diff --git a/resources/lang/en/forms.php b/resources/lang/en/forms.php index 09808d8..5cc99ed 100644 --- a/resources/lang/en/forms.php +++ b/resources/lang/en/forms.php @@ -49,6 +49,10 @@ return [ 'settings_social_facebook_app_secret' => 'Facebook App Secret:', 'settings_social_facebook_login' => 'Allow login/registration with a Facebook account.', 'settings_social_facebook_login_help' => 'With this option enabled, users can register (if enabled) and login with their Facebook account.', + 'settings_social_twitter_app_id' => 'Twitter App ID:', + 'settings_social_twitter_app_secret' => 'Twitter App Secret:', + 'settings_social_twitter_login' => 'Allow login/registration with a Twitter account', + 'settings_social_twitter_login_help' => 'With this option enabled, users can register (if enabled) and login with their Twitter account.', 'settings_social_user_profiles' => 'Enable public user profiles', 'settings_social_user_profiles_help' => 'Display public pages for users showing their albums, cameras used and activity.', 'storage_access_key_label' => 'Access key:', diff --git a/resources/views/themes/base/admin/settings.blade.php b/resources/views/themes/base/admin/settings.blade.php index 4710d11..94fe8bf 100644 --- a/resources/views/themes/base/admin/settings.blade.php +++ b/resources/views/themes/base/admin/settings.blade.php @@ -327,6 +327,7 @@
+ {{-- Facebook --}}
@@ -339,7 +340,7 @@
- +
- + @if ($errors->has('facebook_app_secret')) @@ -370,6 +371,53 @@
+ +
+ + {{-- Twitter --}} +
+
+ +
+ +
+
+ + @lang('admin.settings.social_twitter') + + +
+ + +
+ +
+ + + + @if ($errors->has('twitter_app_id')) +
+ {{ $errors->first('twitter_app_id') }} +
+ @endif +
+ +
+ + + + @if ($errors->has('twitter_app_secret')) +
+ {{ $errors->first('twitter_app_secret') }} +
+ @endif +
+
+
+
diff --git a/resources/views/themes/base/partials/login.blade.php b/resources/views/themes/base/partials/login.blade.php index 3fd6848..542302d 100644 --- a/resources/views/themes/base/partials/login.blade.php +++ b/resources/views/themes/base/partials/login.blade.php @@ -1,8 +1,8 @@ @if (!$is_sso) -

@lang('auth.social_login')

-

- -

+ @if (UserConfig::isSocialMediaLoginEnabled()) +

@lang('auth.social_login')

+ @include(Theme::viewName('partials.social_login_providers')) + @endif

@lang('auth.email_password_login')

@else diff --git a/resources/views/themes/base/partials/register.blade.php b/resources/views/themes/base/partials/register.blade.php index 7c6e3cc..c9b3704 100644 --- a/resources/views/themes/base/partials/register.blade.php +++ b/resources/views/themes/base/partials/register.blade.php @@ -1,8 +1,8 @@ @if (!$is_sso) -

@lang('auth.social_register')

-

- -

+ @if (UserConfig::isSocialMediaLoginEnabled()) +

@lang('auth.social_register')

+ @include(Theme::viewName('partials.social_login_providers')) + @endif

@lang('auth.email_password_register')

@else diff --git a/resources/views/themes/base/partials/social_login_providers.blade.php b/resources/views/themes/base/partials/social_login_providers.blade.php new file mode 100644 index 0000000..927c19b --- /dev/null +++ b/resources/views/themes/base/partials/social_login_providers.blade.php @@ -0,0 +1,8 @@ +

+ @if (UserConfig::get('social_facebook_login')) + + @endif + @if (UserConfig::get('social_twitter_login')) + + @endif +

\ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 3521f5a..d6cecc2 100644 --- a/routes/web.php +++ b/routes/web.php @@ -78,6 +78,8 @@ Route::group(['prefix' => 'install'], function () { Route::get('login/facebook', 'Auth\LoginController@redirectToFacebook')->name('login.facebook'); Route::get('login/facebook/callback', 'Auth\LoginController@handleFacebookCallback')->name('login_callback.facebook'); Route::get('login/sso', 'Auth\LoginController@showLoginFormSso')->name('auth.login_sso'); +Route::get('login/twitter', 'Auth\LoginController@redirectToTwitter')->name('login.twitter'); +Route::get('login/twitter/callback', 'Auth\LoginController@handleTwitterCallback')->name('login_callback.twitter'); Route::get('register/sso', 'Auth\RegisterController@showRegistrationFormSso')->name('auth.register_sso'); // Gallery From c56fe271efd50838072d5976a3895aa937aa5529 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Thu, 16 Aug 2018 14:01:56 +0100 Subject: [PATCH 7/8] #5: Twitter login is now working completely. If the Twitter app is not authorised to access the user's e-mail address, they still have to create a new account. --- app/Http/Controllers/Auth/LoginController.php | 42 +++++++++++++------ app/User.php | 2 +- ...8_16_132300_add_user_twitter_id_column.php | 34 +++++++++++++++ .../themes/base/partials/register.blade.php | 8 ++-- 4 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 database/migrations/2018_08_16_132300_add_user_twitter_id_column.php diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 177a782..6592973 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -152,6 +152,19 @@ class LoginController extends Controller 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(); @@ -163,20 +176,25 @@ class LoginController extends Controller return redirect(route('home')); } - $userByEmailAddress = User::where('email', $socialMediaUser->email)->first(); - - if (!is_null($userByEmailAddress)) + // Some providers (*cough*Twitter*cough*) don't give e-mail addresses without explicit permission/additional + // verification + if (!is_null($socialMediaUser->email)) { - // 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 - ]); + $userByEmailAddress = User::where('email', $socialMediaUser->getEmail())->first(); - return redirect(route('auth.login_sso')); + 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 diff --git a/app/User.php b/app/User.php index 72f3a42..f9c93ed 100644 --- a/app/User.php +++ b/app/User.php @@ -16,7 +16,7 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'name', 'email', 'password', 'is_admin', 'is_activated', 'activation_token', 'enable_profile_page', 'profile_alias', 'facebook_id' + 'name', 'email', 'password', 'is_admin', 'is_activated', 'activation_token', 'enable_profile_page', 'profile_alias', 'facebook_id', 'twitter_id' ]; /** diff --git a/database/migrations/2018_08_16_132300_add_user_twitter_id_column.php b/database/migrations/2018_08_16_132300_add_user_twitter_id_column.php new file mode 100644 index 0000000..092d8df --- /dev/null +++ b/database/migrations/2018_08_16_132300_add_user_twitter_id_column.php @@ -0,0 +1,34 @@ +string('twitter_id')->nullable(true); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) + { + $table->dropColumn('twitter_id'); + }); + } +} diff --git a/resources/views/themes/base/partials/register.blade.php b/resources/views/themes/base/partials/register.blade.php index c9b3704..8e7157e 100644 --- a/resources/views/themes/base/partials/register.blade.php +++ b/resources/views/themes/base/partials/register.blade.php @@ -16,7 +16,7 @@
- + @if ($errors->has('name'))
@@ -30,11 +30,11 @@
- @if ($is_sso) + @if ($is_sso && !empty($register_data['email'])) @else - + @endif @if ($errors->has('email')) @@ -49,7 +49,7 @@
- + @if ($errors->has('password'))
From 98ddb06b76b53b621dd09ad46b692c97421560d6 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Fri, 17 Aug 2018 13:37:58 +0100 Subject: [PATCH 8/8] #5: Implemented login with Google account --- app/Helpers/ConfigHelper.php | 3 ++ .../Controllers/Admin/DefaultController.php | 4 ++ app/Http/Controllers/Auth/LoginController.php | 44 ++++++++++++++++-- app/User.php | 2 +- ...08_17_133429_add_user_google_id_column.php | 34 ++++++++++++++ resources/lang/en/admin.php | 1 + resources/lang/en/forms.php | 4 ++ .../themes/base/admin/settings.blade.php | 45 +++++++++++++++++++ .../partials/social_login_providers.blade.php | 3 ++ routes/web.php | 2 + 10 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 database/migrations/2018_08_17_133429_add_user_google_id_column.php diff --git a/app/Helpers/ConfigHelper.php b/app/Helpers/ConfigHelper.php index b2ee231..168b7a2 100644 --- a/app/Helpers/ConfigHelper.php +++ b/app/Helpers/ConfigHelper.php @@ -106,6 +106,8 @@ class ConfigHelper 'enable_visitor_hits' => false, 'facebook_app_id' => '', 'facebook_app_secret' => '', + 'google_app_id' => '', + 'google_app_secret' => '', 'hotlink_protection' => false, 'items_per_page' => 12, 'items_per_page_admin' => 10, @@ -123,6 +125,7 @@ class ConfigHelper 'smtp_port' => 25, 'smtp_username' => '', 'social_facebook_login' => false, + 'social_google_login' => false, 'social_twitter_login' => false, 'social_user_profiles' => false, 'theme' => 'default', diff --git a/app/Http/Controllers/Admin/DefaultController.php b/app/Http/Controllers/Admin/DefaultController.php index 8553d1c..ad75047 100644 --- a/app/Http/Controllers/Admin/DefaultController.php +++ b/app/Http/Controllers/Admin/DefaultController.php @@ -39,6 +39,7 @@ class DefaultController extends Controller $this->passwordSettingKeys = [ 'smtp_password', 'facebook_app_secret', + 'google_app_secret', 'twitter_app_secret' ]; } @@ -230,6 +231,7 @@ class DefaultController extends Controller 'restrict_original_download', 'smtp_encryption', 'social_facebook_login', + 'social_google_login', 'social_twitter_login', 'social_user_profiles' ]; @@ -239,6 +241,8 @@ class DefaultController extends Controller 'date_format', 'facebook_app_id', 'facebook_app_secret', + 'google_app_id', + 'google_app_secret', 'sender_address', 'sender_name', 'smtp_server', diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 6592973..53009e4 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -10,6 +10,7 @@ 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; @@ -128,6 +129,17 @@ class LoginController extends Controller return $socialite->driver('facebook')->redirect(); } + /** + * Redirect the user to the Google authentication page. + * + * @return \Illuminate\Http\Response + */ + public function redirectToGoogle() + { + $socialite = $this->setSocialiteConfigs(); + return $socialite->driver('google')->redirect(); + } + /** * Redirect the user to the Twitter authentication page. * @@ -152,6 +164,19 @@ class LoginController extends Controller return $this->processSocialMediaLogin($request, 'facebook_id', $facebookUser); } + /** + * Obtain the user information from Google. + * + * @return \Illuminate\Http\Response + */ + public function handleGoogleCallback(Request $request) + { + $socialite = $this->setSocialiteConfigs(); + $googleUser = $socialite->driver('google')->user(); + + return $this->processSocialMediaLogin($request, 'google_id', $googleUser); + } + /** * Obtain the user information from Twitter. * @@ -216,19 +241,30 @@ class LoginController extends Controller 'facebook', function ($app) use ($socialite) { $config = [ - 'client_id' => UserConfig::get('facebook_app_id'), - 'client_secret' => decrypt(UserConfig::get('facebook_app_secret')), + 'client_id' => trim(UserConfig::get('facebook_app_id')), + 'client_secret' => trim(decrypt(UserConfig::get('facebook_app_secret'))), 'redirect' => route('login_callback.facebook') ]; return $socialite->buildProvider(FacebookProvider::class, $config); } ); + $socialite->extend( + 'google', + function ($app) use ($socialite) { + $config = [ + 'client_id' => trim(UserConfig::get('google_app_id')), + 'client_secret' => trim(decrypt(UserConfig::get('google_app_secret'))), + 'redirect' => route('login_callback.google') + ]; + return $socialite->buildProvider(GoogleProvider::class, $config); + } + ); $socialite->extend( 'twitter', function ($app) use ($socialite) { $config = [ - 'identifier' => UserConfig::get('twitter_app_id'), - 'secret' => decrypt(UserConfig::get('twitter_app_secret')), + 'identifier' => trim(UserConfig::get('twitter_app_id')), + 'secret' => trim(decrypt(UserConfig::get('twitter_app_secret'))), 'callback_uri' => route('login_callback.twitter') ]; return new TwitterProvider($app['request'], new TwitterServer($config)); diff --git a/app/User.php b/app/User.php index f9c93ed..0e7f501 100644 --- a/app/User.php +++ b/app/User.php @@ -16,7 +16,7 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'name', 'email', 'password', 'is_admin', 'is_activated', 'activation_token', 'enable_profile_page', 'profile_alias', 'facebook_id', 'twitter_id' + 'name', 'email', 'password', 'is_admin', 'is_activated', 'activation_token', 'enable_profile_page', 'profile_alias', 'facebook_id', 'twitter_id', 'google_id' ]; /** diff --git a/database/migrations/2018_08_17_133429_add_user_google_id_column.php b/database/migrations/2018_08_17_133429_add_user_google_id_column.php new file mode 100644 index 0000000..9d80321 --- /dev/null +++ b/database/migrations/2018_08_17_133429_add_user_google_id_column.php @@ -0,0 +1,34 @@ +string('google_id')->nullable(true); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) + { + $table->dropColumn('google_id'); + }); + } +} diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php index 83e362a..9358efc 100644 --- a/resources/lang/en/admin.php +++ b/resources/lang/en/admin.php @@ -212,6 +212,7 @@ return [ 'security_allow_self_registration' => 'Allow self-registration', 'security_allow_self_registration_description' => 'With this option enabled, users can sign up for their own accounts. You can grant permissions to accounts to allow users to upload their own photos or manage yours.', 'social_facebook' => 'Facebook', + 'social_google' => 'Google', 'social_tab' => 'Social', 'social_twitter' => 'Twitter' ], diff --git a/resources/lang/en/forms.php b/resources/lang/en/forms.php index 5cc99ed..0473b7f 100644 --- a/resources/lang/en/forms.php +++ b/resources/lang/en/forms.php @@ -49,6 +49,10 @@ return [ 'settings_social_facebook_app_secret' => 'Facebook App Secret:', 'settings_social_facebook_login' => 'Allow login/registration with a Facebook account.', 'settings_social_facebook_login_help' => 'With this option enabled, users can register (if enabled) and login with their Facebook account.', + 'settings_social_google_app_id' => 'Google App ID:', + 'settings_social_google_app_secret' => 'Google App Secret:', + 'settings_social_google_login' => 'Allow login/registration with a Google account.', + 'settings_social_google_login_help' => 'With this option enabled, users can register (if enabled) and login with their Google account.', 'settings_social_twitter_app_id' => 'Twitter App ID:', 'settings_social_twitter_app_secret' => 'Twitter App Secret:', 'settings_social_twitter_login' => 'Allow login/registration with a Twitter account', diff --git a/resources/views/themes/base/admin/settings.blade.php b/resources/views/themes/base/admin/settings.blade.php index 94fe8bf..89deec9 100644 --- a/resources/views/themes/base/admin/settings.blade.php +++ b/resources/views/themes/base/admin/settings.blade.php @@ -418,6 +418,51 @@
+ + {{-- Google+ --}} +
+
+ +
+ +
+
+ + @lang('admin.settings.social_google') + + +
+ + +
+ +
+ + + + @if ($errors->has('google_app_id')) +
+ {{ $errors->first('google_app_id') }} +
+ @endif +
+ +
+ + + + @if ($errors->has('google_app_secret')) +
+ {{ $errors->first('google_app_secret') }} +
+ @endif +
+
+
+
diff --git a/resources/views/themes/base/partials/social_login_providers.blade.php b/resources/views/themes/base/partials/social_login_providers.blade.php index 927c19b..13b9377 100644 --- a/resources/views/themes/base/partials/social_login_providers.blade.php +++ b/resources/views/themes/base/partials/social_login_providers.blade.php @@ -5,4 +5,7 @@ @if (UserConfig::get('social_twitter_login')) @endif + @if (UserConfig::get('social_google_login')) + + @endif

\ No newline at end of file diff --git a/routes/web.php b/routes/web.php index d6cecc2..4fd0430 100644 --- a/routes/web.php +++ b/routes/web.php @@ -77,6 +77,8 @@ Route::group(['prefix' => 'install'], function () { // Social media SSO Route::get('login/facebook', 'Auth\LoginController@redirectToFacebook')->name('login.facebook'); Route::get('login/facebook/callback', 'Auth\LoginController@handleFacebookCallback')->name('login_callback.facebook'); +Route::get('login/google', 'Auth\LoginController@redirectToGoogle')->name('login.google'); +Route::get('login/google/callback', 'Auth\LoginController@handleGoogleCallback')->name('login_callback.google'); Route::get('login/sso', 'Auth\LoginController@showLoginFormSso')->name('auth.login_sso'); Route::get('login/twitter', 'Auth\LoginController@redirectToTwitter')->name('login.twitter'); Route::get('login/twitter/callback', 'Auth\LoginController@handleTwitterCallback')->name('login_callback.twitter');