I am using laravel version 5.4.36 and i am using Laravel Sociallite plugin to connect user with facebook.
I want to get uploaded pictures of logged in user as suggested in the document This is available through the photos edge on the User object.
public function redirect()
{
// return Socialite::driver('facebook')->redirect();
return Socialite::driver('facebook')->fields([
'first_name', 'last_name', 'email', 'gender', 'birthday','location','hometown','age_range','friends','posts','photos'
])->scopes([
'email', 'user_birthday','user_gender','user_location','user_hometown',
'user_age_range','user_friends','user_link','user_photos','user_posts',
'user_tagged_places','user_videos','user_likes',
])->redirect();
}
In above code, I have requested
user_photo as scope and photos as fields
my callback function is
public function callback(SocialFacebookAccountService $service)
{
$user = $service->createOrGetUser(Socialite::driver('facebook')->fields([
'name', 'email', 'birthday','gender','location','hometown','age_range','friends','link',
'photos','posts','tagged_places','videos','likes',
])->user());
auth()->login($user);
return redirect()->to('/home');
}
where i have requested photos still i am not able to get photo age when i do
namespace App\Services;
use App\SocialFacebookAccount;
use App\User;
use Laravel\Socialite\Contracts\User as ProviderUser;
use File;
class SocialFacebookAccountService
{
public function createOrGetUser(ProviderUser $providerUser)
{
echo "<pre>"; print_r($providerUser);die;
$account = SocialFacebookAccount::whereProvider('facebook')
->whereProviderUserId($providerUser->getId())
->first();
if ($account) {
return $account->user;
} else {
$account = new SocialFacebookAccount([
'provider_user_id' => $providerUser->getId(),
'provider' => 'facebook'
]);
$user = User::whereEmail($providerUser->getEmail())->first();
// echo "<pre>";print_r($user);die;
if(!empty($providerUser->getAvatar())){
$fileContents = file_get_contents($providerUser->getAvatar());
File::put(public_path() . '/uploads/profile/' . $providerUser->getId() . ".jpg", $fileContents);
}
$imageUrl = $providerUser->getId() . ".jpg";
// echo "<pre>";print_r($providerUser->user);die;
if (!$user) {
$user = User::create([
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'password' => md5(rand(1,10000)),
'avatar'=> $imageUrl,
'birthday' => $providerUser->user['birthday'],
'gender' => $providerUser->user['gender'],
'age_range' =>$providerUser->user['age_range']['min'],
'total_friends'=>$providerUser->user['friends']['summary']['total_count'],
'profile_link'=>$providerUser->user['link'],
]);
}
$account->user()->associate($user);
$account->save();
return $user;
}
}
}
Have print in the starting of the createOrGetUser function but still i am not able to get photo age under the user object.
Any suggestions please.
Related
So I just want to add login with google feature on my working authentication web app (with Codeigniter Shield package). I've already create a login_google function on Login controller that extends LoginController from shield package like this :
LoginController
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\Shield\Controllers\LoginController;
class Login extends LoginController
{
function __construct()
{
require_once __DIR__ . '/../../vendor/autoload.php';
$this->userModel = new \App\Models\UserModel();
$this->google_client = new \Google_Client();
$this->google_client->setClientId(getenv('OAuth2.clientID'));
$this->google_client->setClientSecret(getenv('OAuth2.clientSecret'));
$this->google_client->setRedirectUri('http://localhost:8080/login_google');
$this->google_client->addScope('email');
$this->google_client->addScope('profile');
}
public function loginView()
{
if (auth()->loggedIn()) {
return redirect()->to(config('Auth')->loginRedirect());
}
/** #var Session $authenticator */
$authenticator = auth('session')->getAuthenticator();
// If an action has been defined, start it up.
if ($authenticator->hasAction()) {
return redirect()->route('auth-action-show');
}
$data['google_button'] = "<a href='".$this->google_client->createAuthUrl()."'><img src='https://developers.google.com/identity/images/btn_google_signin_dark_normal_web.png' /></a>";
return view('login', $data);
}
public function loginAction(): RedirectResponse
{
// Validate here first, since some things,
// like the password, can only be validated properly here.
$rules = $this->getValidationRules();
if (! $this->validate($rules)) {
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
}
$credentials = $this->request->getPost(setting('Auth.validFields'));
$credentials = array_filter($credentials);
$credentials['password'] = $this->request->getPost('password');
$remember = (bool) $this->request->getPost('remember');
/** #var Session $authenticator */
$authenticator = auth('session')->getAuthenticator();
// Attempt to login
$result = $authenticator->remember($remember)->attempt($credentials);
if (! $result->isOK()) {
return redirect()->route('login')->withInput()->with('error', $result->reason());
}
/** #var Session $authenticator */
$authenticator = auth('session')->getAuthenticator();
// If an action has been defined for login, start it up.
if ($authenticator->hasAction()) {
return redirect()->route('auth-action-show')->withCookies();
}
return redirect()->to(config('Auth')->loginRedirect())->withCookies();
}
public function login_google() {
$token = $this->google_client->fetchAccessTokenWithAuthCode($this->request->getVar('code'));
if (!isset($token['error'])) {
$this->google_client->setAccessToken($token['access_token']);
$this->session->set('access_token', $token['access_token']);
$google_service = new \Google\Service\Oauth2($this->google_client);
$data = $google_service->userinfo->get();
$userdata = array();
if ($this->userModel->isAlreadyRegister($data['id'])) {
$userdata = [
'first_name' => $data['givenName'],
'last_name' => $data['familyName'],
'email' => $data['email'],
'avatar' => $data['picture'],
];
$this->userModel->updateUserData($userdata, $data['id']);
} else {
$userdata = [
'first_name' => $data['givenName'],
'last_name' => $data['familyName'],
'email' => $data['email'],
'avatar' => $data['picture'],
'oauth_id' => $data['id'],
];
$this->userModel->insertUserData($userdata);
}
$this->session->set('LoggedUserData', $userdata);
} else {
$this->session->set("error", $token['error']);
return redirect('/register');
}
return redirect()->to('/profile');
}
}
UserModel like this :
UserMode
<?php
namespace App\Models;
use CodeIgniter\Model;
use CodeIgniter\Shield\Models\UserModel as ModelsUserModel;
class UserModel extends ModelsUserModel
{
protected $allowedFields = [
'username',
'status',
'status_message',
'active',
'last_active',
'deleted_at',
'gender',
'first_name',
'last_name',
'avatar',
'phone_number',
'full_address',
'oauth_id',
];
function isAlreadyRegister($authid){
return $this->db->table('users')->getWhere(['id'=>$authid])->getRowArray()>0?true:false;
}
function updateUserData($userdata, $authid){
$this->db->table("users")->where(['id'=>$authid])->update($userdata);
}
function insertUserData($userdata){
$this->db->table("users")->insert($userdata);
}
}
But everytime I clicked sign in with google button, it won't work (the interface for choosing google account to authenticate is worked) and always return to login page
am I missing something when combining CodeIgniter Shield with Google Oauth ? Anyone can help ? TIA
A new package has been created for OAuth with Shield package: https://github.com/datamweb/shield-oauth
You can use it instead of your own one.
If you set relation ships between the User.php return $this->belongsTo('App\User'); and Profile.php return $this->hasOne('App\Profile', 'user_id', 'id'); how can u get a corresponding user to the profile when you only get the Profile variables. public function update(Request $request, Profile $profile)
i was thinking of something like this User::where(user->id==$profile->id); but its not working how would can you do it?
mine hole function:
if(\Auth::check()) {
if(\Auth::user()->type == 'admin'){
$validated = $request->validate([
'username' => 'required',
'email' => 'required|email',
'firstname' => 'required',
'lastname' => 'required',
'age' => 'required|numeric|max:150',
'birthdate' => 'required|numeric',
'bio' => 'required|min:30',
'select_file' => 'image|mimes:jpg,png,gif,jpeg|max:2048'
]);
$image = $request->file('select_file');
$new_name = rand() . '.' . $image->getClientOriginalExtension();
$image->move(public_path('images'), $new_name);
$profile->username = $validated['username'];
$profile->email = $validated['email'];
$profile->firstname = $validated['firstname'];
$profile->lastname = $validated['lastname'];
$profile->age = $validated['age'];
$profile->birthdate = $validated['birthdate'];
$profile->bio = $validated['bio'];
$profile->image_path = $new_name;
$profile->update();
$user = User::where(user->id==$profile->id);
$user->name = $validated['username'];
$user->email = $validated['email'];
$user->update();
return redirect()
->route('admin')
->with('succes', 'Profile updated succesfully');
} else {
return redirect()
->route('admin')
->with('fail', 'Profile is unable to be update successfully');
}
} else {
return redirect()
->route('login')
->with('fail', 'Profile is unable to be update successfully
because ur not an Admin');
}
Your where is not formatted properly. You need to pass in 2 (or 3) parameters, where the first is the column, and the second is the value you're checking for. If using 3 parameters, the second would be the operator (= or !=). Don't forget first() (for one record) or get() (for a collection of records), so that the query actually runs. Otherwise, it will just be the QueryBuilder object.
User::where('id', $profile->user_id)->first();
or
User::where('id','=', $profile->user_id)->first();
Since you're checking against the user's id, you can also use find() to get one record:
User::find($profile->user_id);
You can do it some ways.
Solution 1:
User::whereId($profile->user_id)->first();
Solution 2:
User::where('id', $profile->user_id)->first();
Solution 3:
User::where('id','=', $profile->user_id)->first();
Solution 4:
User::where(['id' => $profile->user_id])->first();
Also you can do it
In Profile model define
public function user()
{
return $this->belongsTo('App\User');
}
Than you can lazy load
$user = $profile->load('user')->user; // but it is lazy loading
I'm trying to login a user through laravel socialite. Everything is working fine but the user is not getting logged in!
I'm getting response from facebook, saving the response in the database and trying to login after that.
here is the code:
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Laravel\Socialite\Two\InvalidStateException;
use Auth;
use Socialite;
use App\User;
use DB;
use Log;
public function handleProviderCallback($provider)
{
$social = Socialite::driver($provider)->user();
$findUser = User::where('email', $social->email)->first();
if ($findUser) {
// dd($findUser); **************** This returns information of the user who is trying to login through facebook
// dd(Auth::login($findUser, true)); ***************** This line returns null
if (Auth::login($findUser, true)) {
// dd(Auth::loginUsingId($findUser->id, true));
redirect()->route('dashboard');
} else {
return 'Error'; //**************** This get echoed on the screen
}
} else {
$user = new User();
$user->name = $social->name;
$user->email = $social->email;
$user->avatar = $social->avatar;
$user->provider = $provider;
$user->id = $social->id;
$user->password = bcrypt('password');
$user->save();
}
if (Auth::login($user)) {
return redirect()->intended('/home');
} else {
return 'Error';
}
}
Neither register, nor login is working.
The login() method doesn't return anything so if (Auth::login($findUser, true)) will never pass.
Also, it might be worth using the firstOrCreate() to make your method smaller:
public function handleProviderCallback($provider)
{
$social = Socialite::driver($provider)->user();
User::unguard();
$user = User::firstOrCreate([
'email' => $social->email,
], [
'id' => $social->id,
'name' => $social->name,
'avatar' => $social->avatar,
'provider' => $provider,
'password' => bcrypt('password'),
]);
auth()->login($user, true);
return redirect()->intended('/home');
}
If you want to check if the User is signed in then you can use the auth()->id() method to retrieve the current authenticated user's id and then compare that to the $user->id:
if (auth()->id() !== $user->id) {
return 'Error';
}
Obviously, if you prefer to use the Auth facade instead of the auth() helper function then you can use Auth::id() instead of auth()->id()
I am using Socialite to login/register with facebook into my application. When I dump my $facebookUser variable I see this json :
$facebookuser :
But when I try to store the id and avatar , it doesn't store it and I can't display the users profile picture of facebook. I am using laravel to store my user.
AuthController.php :
public function handleProviderCallback()
{
try {
$user = Socialite::driver('facebook')->user();
} catch (Exception $e) {
return redirect('auth/facebook');
}
$authUser = $this->findOrCreateUser($user);
Auth::login($authUser, true);
return redirect()->route('home')->with('successfullFacebookLogin', Auth::user()->name);
}
private function findOrCreateUser($facebookUser)
{
// When I dd($facebookuser) it gives json stated above
$authUser = User::where('facebook_id', $facebookUser->id)->first();
if ($authUser){
return $authUser;
}
return User::create([
'name' => $facebookUser->name,
'email' => $facebookUser->email,
'facebook_id' => $facebookUser->user['id'],
'avatar' => $facebookUser->avatar,
'facebookAccount' => 1
]);
}
Use Laravel Socialite provided methods to access user details rather than access the property directly, here is list of available methods for all built-in providers:
$user->getId();
$user->getNickname();
$user->getName();
$user->getEmail();
$user->getAvatar();
So your code should be:
private function findOrCreateUser($facebookUser)
{
// When I dd($facebookuser) it gives json stated above
$authUser = User::where('facebook_id', $facebookUser->id)->first();
if ($authUser){
return $authUser;
}
return User::create([
'name' => $facebookUser->getName(),
'email' => $facebookUser->getEmail(),
'facebook_id' => $facebookUser->getId(),
'avatar' => $facebookUser->getAvatar(),
'facebookAccount' => 1
]);
}
Don't forget to state those columns above in $fillable property of User model:
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'facebook_id', 'avatar', 'facebookAccount'
];
Otherwise fill the attributes manually:
$user = new User;
$user->name = $facebookUser->getName();
$user->email = $facebookUser-> getEmail();
$user->facebook_id = $facebookUser->getId();
$user->facebookAccount = 1;
$user->save();
return $user;
I'm using Socialite to get user information from facebook. All is going well but my redirect isn't working
Sub-routes
I read that it's not possible to do a redirect from a submethod, or
any method that's not in your routes.
But how else can i redirect the user after I logged them in?
My URL looks like this after the successfull facebook handshake
http://tmdb.app/auth/login/facebook?code=AQBTKNZIxbfdBruAJBqZ8xx9Qnz...
Code
class SocialController extends Controller {
public function login(Authenticate $authenticate, Request $request)
{
return $authenticate->execute($request->has('code'), $this);
}
public function userHasLoggedIn($data)
{
$user = User::where('provider_id', $data->id)->first();
if( !$user )
{
$user = User::create([
'name' => $data->name,
'email' => $data->email,
'provider' => 'facebook',
'provider_id' => $data->id
]);
}
// NOT WORKING!
return redirect('test');
}
}
Your login function should be handling the redirect.
I'm guessing execute returns $data if the user is sucessfully logged in and false if not.
class SocialController extends Controller {
public function login(Authenticate $authenticate, Request $request)
{
if($data = $authenticate->execute($request->has('code'), $this))
{
$user = User::where('provider_id', $data->id)->first();
// maybe delegate the user creation to another class/service?
if( !$user )
{
$user = User::create([
'name' => $data->name,
'email' => $data->email,
'provider' => 'facebook',
'provider_id' => $data->id
]);
}
return redirect('test');
}
return redirect('fail_view');
}
}
You can do it using PHP header function in Laravel sub method. I try it and works properly. Hope it can help you.
// You can using the following code
$url= url("about-laravel");
header("Location:" . $url);
exit;
// Or using the following code to redirect and keep set flash message
$result= $this->yourMethod(); // return redirect($this->route)->with('flash_message', 'I\'m Flash Message'); for TRUE or NULL for false
if( $result ){
return $result;
}