Skip to content

Instantly share code, notes, and snippets.

@aliukevicius
Created May 20, 2016 05:48
Show Gist options
  • Save aliukevicius/f616a941f7b9f602841e6fa832dbc24e to your computer and use it in GitHub Desktop.
Save aliukevicius/f616a941f7b9f602841e6fa832dbc24e to your computer and use it in GitHub Desktop.
<?php
use Facebook\FacebookSession;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;
use App\Repositories\Oauth\OauthRepositoryInterface;
use App\Repositories\User\UserRepositoryInterface;
use App\Entities\User as UserEntity;
use App\Repositories\UserProfile\UserProfileRepositoryInterface;
use App\Exceptions\ValidationException;
use App\Services\Validators\UserValidator;
use App\Repositories\File\FileRepositoryInterface;
use App\Entities\File;
class OauthController extends \BaseController {
protected $userRepository;
protected $userProfileRepository;
protected $fileRepository;
public function __construct(
OauthRepositoryInterface $oauthRepositoryInterface,
UserRepositoryInterface $userRepositoryInterface,
UserProfileRepositoryInterface $userProfileRepositoryInterface,
FileRepositoryInterface $fileRepositoryInterface,
UserValidator $validator
)
{
$this->repository = $oauthRepositoryInterface;
$this->userRepository = $userRepositoryInterface;
$this->userProfileRepository = $userProfileRepositoryInterface;
$this->validator = $validator;
$this->fileRepository = $fileRepositoryInterface;
$this->translationFile = 'oauth';
}
public function fbAuth()
{
$error = Input::get('error');
$authAction = Session::get('fbAuthAction');
if ($error != null) {
if ($authAction == 'register') {
return $this->returnResponse('user.registerForm');
} else if ($authAction == 'linkAccount') {
return $this->returnResponse('user.profileEditForm');
} else {
return Redirect::to('/');
}
}
$loginHelper = $this->getFbLoginHelper(Request::url());
try {
$session = $loginHelper->getSessionFromRedirect();
} catch(\Exception $ex) {
Notification::error($this->t('oAuthError'));
return Redirect::to('/');
}
if ($session) {
// authentication successful.
$request = new FacebookRequest($session, 'GET', '/me');
$response = $request->execute();
$fbUserData = $response->getGraphObject()->asArray();
$request = new FacebookRequest($session, 'GET', '/me/permissions');
$response = $request->execute();
$permissions = $response->getGraphObject()->asArray();
// check if we have permission to see users email address
foreach ($permissions as $p) {
if ($p->permission == 'email' && $p->status != 'granted') {
// we need to know that on next auth attempt we need to rerequest permissions
Session::set('fbAuthReRequestPermissions', true);
Notification::error(t('oauth.fbNeedEmailPermission'));
if ($authAction == 'linkAccount') {
return $this->returnResponse('user.profileEditForm');
} else {
return Redirect::to('/'); // redirect user to frontPage
}
}
}
// we have needed permission and don't need to reRequest them nex time
Session::remove('fbAuthReRequestPermissions');
$token = $session->getAccessToken()->extend(); // get extended token
if ($authAction == 'register') {
$oAuth = $this->repository->getOauth('facebook', $fbUserData['id']);
// if user with this FB account doesn't exist
if ($oAuth == null) {
$userData = [
'email' => $fbUserData['email'],
// set random string as password. Until user changes his password he won't be able to login with password
'password' => 'oauth', // just so we know that user doesn`t have real password
'status' => UserEntity::$statusIncompleteProfile, // because we don't get Fb picture
];
try {
$this->validator->isValidOauthRegsiter($userData, $this->translationFile); // check if email is unique
} catch (ValidationException $e) {
return $this->returnResponse('user.registerForm', null, $this->t('oauthRegisterDublicateEmail'));
}
$gender = 'M';
if (isset($fbUserData['gender'])) {
$gender = $fbUserData['gender'] == 'male' ? 'M' : 'F';
}
$userProfileData = [
'first_name' => $fbUserData['first_name'],
'last_name' => $fbUserData['last_name'],
'sex' => $gender,
'public_phone' => 1,
'public_additional_phone' => 1
];
$user = $this->userRepository->create($userData);
$this->userRepository->addUserRole($user->user_id, 'Authenticated');
$userProfileData['user_id'] = $user->user_id;
// get user picture from FB
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://graph.facebook.com/'.$fbUserData['id'].'/picture?redirect=0&height=250&type=normal&width=200');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, TRUE);
$pictureData = json_decode(curl_exec ($ch), true);
curl_close($ch);
if (isset($pictureData['data']['url'])) { // check if we have the picture data
$file = $this->fileRepository->addFileFromUrl($pictureData['data']['url'], $user->user_id, File::$statusPermanent);
$userProfileData['profile_picture'] = $file->file_id;
}
$this->userProfileRepository->create($userProfileData);
$this->repository->create([
'user_id' => $user->user_id,
'provider' => 'facebook',
'token' => (string) $token,
'provider_id' => $fbUserData['id'],
'expires' => $token->getExpiresAt()->format('Y-m-d H:i:s'),
]);
CAuth::loginUsingId($user->user_id);
Event::fire('user.registered.facebook', [$user]);
return $this->returnResponse('user.profileEditForm');
} else { // FB user already linked with our systems user. Just log in the user
$user = $oAuth->user;
if ($user != null) {
$oAuth = $this->repository->update($oAuth->oauth_id, [
'token' => (string) $token,
'expires' => $token->getExpiresAt()->format('Y-m-d H:i:s')
]);
CAuth::login($user);
} else {
$authErrors[] = $this->t('oAuthError');
}
}
return Redirect::to('/');
} else if ($authAction == 'linkAccount') {
$oAuth = $this->repository->getOauth('facebook', $fbUserData['id']);
if ($oAuth == null) {
$app = $this->getApp();
$this->repository->create([
'user_id' => $app->user->user_id,
'provider' => 'facebook',
'token' => (string) $token,
'provider_id' => $fbUserData['id'],
'expires' => $token->getExpiresAt()->format('Y-m-d H:i:s'),
]);
return $this->returnResponse('user.profileEditForm', $this->t('facebbokAccountLinked'));
} else { // user FB user already linked with our systems user. Just logg in the user
return $this->returnResponse('user.profileEditForm', null, $this->t('facebookProfileLinkedWithOtherUser'));
}
} else {
$oAuth = $this->repository->getOauth('facebook', $fbUserData['id']);
if ($oAuth != null) {
$user = $oAuth->user;
if ($user != null) {
$oAuth = $this->repository->update($oAuth->oauth_id, [
'token' => (string) $token,
'expires' => $token->getExpiresAt()->format('Y-m-d H:i:s')
]);
CAuth::login($user);
} else {
$authErrors[] = $this->t('oAuthError');
}
} else { // no user found linked with this FB account
return $this->returnResponse('user.loginForm', null, $this->t('oauthLoginFacebookNoUser'));
}
return Redirect::to('/');
}
}
// we should`t get to this point but if we get here get into panic mode and throw up.
throw new Exception("Facebook authentication error. Cant acquire session.");
}
/**
* Do Facebook authentication redirect
*
* @param $type - action type for which we performing this authentication
* @return \Illuminate\Http\RedirectResponse
*/
protected function doFbAuth($type)
{
Session::set('fbAuthAction', $type);
$scopes = \Config::get('oauth.providers.Facebook.scope');
$loginHelper = $this->getFbLoginHelper(URL::to('/oauth/fb'));
$reRequestPermissions = Session::get('fbAuthReRequestPermissions', false);
if ($reRequestPermissions) {
return Redirect::to($loginHelper->getReRequestUrl($scopes));
}
return Redirect::to($loginHelper->getLoginUrl($scopes));
}
/**
* Login via oAuth provider
*/
public function login()
{
return $this->doFbAuth('login');
}
/**
* Register via oAuth provider
*/
public function register()
{
return $this->doFbAuth('register');
}
/**
* Link account with oAuth provider
*/
public function linkAccount()
{
return $this->doFbAuth('linkAccount');
}
protected function getFbLoginHelper($redirectBackTo)
{
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
$appId = \Config::get('oauth.providers.Facebook.client_id');
$appSecret = \Config::get('oauth.providers.Facebook.client_secret');
FacebookSession::setDefaultApplication($appId, $appSecret);
$helper = new FacebookRedirectLoginHelper($redirectBackTo);
return $helper;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment