I'm using Socialite to provide authentication via account providers (Facebook, Twitter, LinkedIn ...).
In my application, when performing authentication via provider, if there is already an association of the current account of the user with the account of the provider it will be logged, if there is no current link with the account of the provider, an association will be made with the cadastre current, if you do not have a registration it will be created (user redirected to a view for the purpose of confirming only your name).
routes / web.php
Route::get('auth-socialite/{provider}', 'Auth\SocialiteController@redirectToProvider');
Route::get('auth-socialite/{provider}/callback', 'Auth\SocialiteController@handleProviderCallback');
Route::post('auth-socialite/criar-usuario', 'Auth\SocialiteController@createUser');
SocialiteController.php
<?php
namespace App\Http\Controllers\Auth;
use Auth;
use Socialite;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\ProvedoresServicoContas;
class SocialiteController extends Controller
{
/**
* Endereço para onde o usuário será redirecionado após o login
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Chama a página de autenticação do provedor (Facebook, Linkedin, Twitter...)
*
* @param $provedor
* @return mixed
*/
public function redirectToProvider($provedor)
{
return Socialite::driver($provedor)->redirect();
}
/**
* Autentica o usuário via callback do provedor (Facebook, Linkedin, Twitter...)
*
* @param $provedor
* @return \Illuminate\Http\RedirectResponse
*/
public function handleProviderCallback($provedor)
{
$userProvedor = Socialite::driver($provedor)->user();
$authUsuario = $this->findOrCreateUser($userProvedor, $provedor);
if (!$authUsuario)
return view('auth.socialite-novo-user', compact('userProvedor', 'provedor'));
Auth::login($authUsuario, true);
return redirect($this->redirectTo);
}
/**
* Se o usuário já existe o mesmo será retornado, do contrário será criado
*
* @param $userProvedor
* @param $provedor
* @return \App\Models\User
*/
public function findOrCreateUser($userProvedor, $provedor)
{
$conta = ProvedoresServicoContas::whereProvedor($provedor)
->whereProvedorUserId($userProvedor->getId())
->first();
if ($conta)
return $conta->user;
$usuario = User::whereEmail($userProvedor->getEmail())->first();
if (!$usuario) {
session(['userProvedor' => $userProvedor, 'provedor' => $provedor]);
return false;
}
return $this->associarProvedorUsuario($usuario, $userProvedor, $provedor);
}
public function createUser(Request $request)
{
$userProvedor = session('userProvedor');
$provedor = session('provedor');
$usuario = User::create([
'name' => $request->name,
'email' => $userProvedor->email,
'password' => bcrypt(str_random(20)),
]);
$this->associarProvedorUsuario($usuario, $userProvedor, $provedor);
Auth::login($usuario, true);
return redirect($this->redirectTo);
}
public function associarProvedorUsuario($usuario, $userProvedor, $provedor)
{
$criarConta = new ProvedoresServicoContas([
'provedor_user_id' => $userProvedor->getId(),
'provedor' => $provedor
]);
$criarConta->user()->associate($usuario);
$criarConta->save();
return $usuario;
}
}
migrate:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateProvedoresServicoContasTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('provedores_servico_contas', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->string('provedor');
$table->string('provedor_user_id');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('provedores_servico_contas');
}
}
Currently it is working, though, I think my controller is confusing. Any suggestions for improvement in terms of organization and efficiency?