Laravel Passport and Ionic2 Facebook-Login - facebook

I am developing a mobile app which should do API calls to an own laravel backend.
Frontend: Ionic 2 + Angular2
Backend: Laravel 5.3 + Laraval Passport + MySQL
At the user can log in with password grant (username + password).
Now I want to offer a login via Facebook.
I've implemented a Login with Facebook-button in the app. This works fine. I get the profile information from the Facebook API: id, email, name
Now this user (has no email + password combination from our server) should be able to make API calls to our Laravel server and should be linked to user in the users-table of the MySQL-database behind the laravel backend. Users which login with Facebook shouldn't need any username or password to login. Just Facebook.
I want to generate a new user in the database for each facebook user (simply with a column facebook_id). But how to give such users an access_token?
Accepting just the Facebook ID, match this (or create new) user in the database and create an access_token would be very unsecure because Facebook ID is public...

I must say I have same problem couple of weeks ago. Only difference I got was that I have both, ionic2 app and website. Both must support username/password login as social login (google, facebook).
So how did I did that (I will write for facebook, google is slightly different - better):
Prepare your facebook app to accept logins from mobile AND webpage. You will need facebook client_id and client_secret.
Install socialite package for laravel. And set it up to work with facebook ( in app/services.php set facebook ).
Now when you got this you can start coding. You said you already have it working on Ionic2 part. So that means you get token and other data from facebook for user.
What I did is I make request to my api and send this token and user_id. Then on my API side I check if token is valid, login user and issue passport token.
Ionic2 code:
Facebook.login(["public_profile"])
.then(response => {
// login success send response to api and get token (I have auth service class to do that)
this.auth.facebookLogin(response.authResponse).then(
...
);
}, error => {
this.showAlert( this.loginFailedTitle, this.loginFailedText );
});
Now Laravel part. I made SocialController.php and url (POST request) /api/social-login/facebook:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Model\SocialLogin;
use App\User;
use Illuminate\Http\Request;
use Socialite;
class SocialController extends Controller
{
public function facebook(Request $request) {
$user = Socialite::driver('facebook')->userFromToken( $request->input('accessToken'));
abort_if($user == null || $user->id != $request->input('userID'),400,'Invalid credentials');
// get existing user or create new (find by facebook_id or create new record)
$user = ....
return $this->issueToken($user);
}
private function issueToken(User $user) {
$userToken = $user->token() ?? $user->createToken('socialLogin');
return [
"token_type" => "Bearer",
"access_token" => $userToken->accessToken
];
}
}
Now this will return you passport token and you can make api request to protected routes.
About passport, email, username, ..... you will have to change database and make it nullable. And add facebook_id field.
And be sure to make requests over https, because your are sending token.
Hope it helps.

in addition to #Bostjan's answer adding my generalised implementation :
SocialAccount here is a laravel model where you'll provider and provider_user_id and local database user id. Below is the example of social_accounts table
And in SocialController :
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use App\User;
use App\SocialAccount;
use Socialite;
class SocialController extends Controller
{
public function social(Request $request) {
$provider = $request->input('provider');
switch($provider){
case SocialAccount::SERVICE_FACEBOOK:
$social_user = Socialite::driver(SocialAccount::SERVICE_FACEBOOK)->fields([
'name',
'first_name',
'last_name',
'email'
]);
break;
case SocialAccount::SERVICE_GOOGLE:
$social_user = Socialite::driver(SocialAccount::SERVICE_GOOGLE)
->scopes(['profile','email']);
break;
default :
$social_user = null;
}
abort_if($social_user == null , 422,'Provider missing');
$social_user_details = $social_user->userFromToken($request->input('access_token'));
abort_if($social_user_details == null , 400,'Invalid credentials'); //|| $fb_user->id != $request->input('userID')
$account = SocialAccount::where("provider_user_id",$social_user_details->id)
->where("provider",$provider)
->with('user')->first();
if($account){
return $this->issueToken($account->user);
}
else {
// create new user and social login if user with social id not found.
$user = User::where("email",$social_user_details->getEmail())->first();
if(!$user){
// create new social login if user already exist.
$user = new User;
switch($provider){
case SocialAccount::SERVICE_FACEBOOK:
$user->first_name = $social_user_details->user['first_name'];
$user->last_name = $social_user_details->user['last_name'];
break;
case SocialAccount::SERVICE_GOOGLE:
$user->first_name = $social_user_details->user['name']['givenName'];
$user->last_name = $social_user_details->user['name']['familyName'];
break;
default :
}
$user->email = $social_user_details->getEmail();
$user->username = $social_user_details->getEmail();
$user->password = Hash::make('social');
$user->save();
}
$social_account = new SocialAccount;
$social_account->provider = $provider;
$social_account->provider_user_id = $social_user_details->id;
$user->social_accounts()->save($social_account);
return $this->issueToken($user);
}
}
private function issueToken(User $user) {
$userToken = $user->token() ?? $user->createToken('socialLogin');
return [
"token_type" => "Bearer",
"access_token" => $userToken->accessToken
];
}
}

Related

Integration AspNet.Security.OpenId.Providers Steam authorization with reactive.js?

I have a ASP.Net Core 2.2 Web API which uses Steam login for authentication using this package.
My authentication looks like this:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/Api/Login";
options.LogoutPath = "/Api/Logout";
})
.AddSteam(opt => { opt.CallbackPath = "/Home/SteamCallback"; opt.ApplicationKey = "XXXX"; });
I'm using this API with my react app and I want to login so I added this in my react project to login
Via Steam
And /api/login redirects user back to react's homepage:
[HttpGet("/api/login")]
public IActionResult Login(string provider="Steam")
{
return Challenge(new AuthenticationProperties { RedirectUri = "http://localhost:3000/" }, provider);
}
I know it's so stupid to try authorize like that but i dont have any idea how.
Also they say using JWT is not safe in here so I had to use cookies but could not handle how to pass logged data to react and fetch data successfully.

Socialite redirect the user after successful facebook registeration

I'm using Laravel 5.5 and using Socialite to register users via facebook, this is my handleProviderCallback
public function handleProviderCallback(Request $request)
{
$state = $request->get('state');
$request->session()->put('state',$state);
session()->regenerate();
$user = Socialite::driver('facebook')->user();
$userInsert = new User();
$userInsert->name = $user->getName();
$userInsert->email = $user->getEmail();
$userInsert->password = bcrypt('password');
$userInsert->save();
return redirect()->guest('admin/dashboard');
}
the user is inserted successfully in the database but i can't redirect him to "admin/dashboard" how to do it.
Try to force the user to login before redirect him/her to dashboard:
Insert this:
\Auth::login($userInsert, true);
Before:
return redirect()->guest('admin/dashboard');

Meteor facebook login - user is not show in SignIn space

I try to add Facebook login function on my app, it work but I have some problems
I start with:
meteor add accounts-password
meteor add accounts-ui
meteor add service-configuration
meteor add accounts-facebook
Then I write a test app on facebook, adding login and get my appId and secret
I copy documentation's code to configure settings (server side) and I put my appId and secret
ServiceConfiguration.configurations.upsert(
{ service: "facebook" },
{
service : "facebook",
appId: '123456789012345678',
secret: '123456789012345678123456789012345678123456789012345678',
loginStyle : "popup",
requestPermissions: ['email','user_friends']
}
);
I try to login with facebook and I have (showing in console.log) all the data I need (the picture is the picture profile in facebook), but the SignIn name is nto show in the top of the app
When I signin with a normal email password login I have no problem
The problem was in this function:
Accounts.onCreateUser(function(options, user) {
var imgAvatar = "/img/user.png";
var username = "NewPlayer_" + Math.floor(Math.random() * (9000 - 1000) + 1000);
if (user.hasOwnProperty('services') && user.services.hasOwnProperty('facebook') ) {
imgAvatar = "http://graph.facebook.com/" + user.services.facebook.id + "/picture/?type=small";
username = user.services.facebook.name;
}
return user;
});
I discover the correct way to use this function in this post
Accounts.onCreateUser((function(_this) {
return function(options, user) {
options = {
username: 'pippo'
}
return Object.assign({}, user, options);
};
})(this));

Cannot login through Facebook in Laravel 5.1

I am trying to login with facebook using Laravel 5.1.
I am following each steps mention in laravel documentation.
http://laravel.com/docs/5.1/authentication#social-authentication.
But, When i login through facebook then it will redirect to my normal login page.
In sort Session is store in facebook login.
This is a Code that is written by me.
Router.php
Route::get('auth/facebook','Auth\AuthController#redirectToProvider');
Route::get('auth/facebook/callback','Auth\AuthController#handleProviderCallback');
AuthController.php
public function redirectToProvider()
{
return Socialite::driver('facebook')
->scopes(['email', 'public_profile'])
->redirect();
}
public function handleProviderCallback()
{
$user = Socialite::driver('github')->user();
$user = Socialite::driver('github')->user();
// OAuth Two Providers
$token = $user->token;
// OAuth One Providers
$token = $user->token;
$tokenSecret = $user->tokenSecret;
// All Providers
$user->getId();
$user->getNickname();
$user->getName();
$user->getEmail();
$user->getAvatar();
}
Services.php
'facebook' => [
'client_id' => '1625567400000000',
'client_secret' => 'secret',
'redirect' => 'http://localhost:8000/',
],
When i type localhost/8000/auth/facebook it will redirect me to facebook and ask permission for public_profile, email etc.
And it will redirect back to localhost/auth/login.
And when i type localhost:8000/auth/facebook/callback in URL, it will through error like this;
ClientException in Middleware.php line 69:
Client error: 404
For your case, I guest you are using middleware to check if the user is already logged in. And this might the problem that you get redirect to localhost/auth/login
I hope following code could be useful to you
public function handleProviderCallback()
{
//retrieve user's information from facebook
$socUser = Socialite::driver('facebook')->user();
//check user already exists in db
$user = \App\User::where('email', $socUser->getEmail())->first();
if($user) {
// if exist, log user into your application
// and redirect to any path you want
\Auth::login($user);
return redirect()->route('user.index');
}
//if not exist, create new user,
// log user into your application
// and resirect to any path you want
$user = new \App\User ;
$user->email = $socUser->getEmail();
// ...
// ...
// ...
$user->save();
\Auth::login($user); // login user
return redirect()->route('user.index'); // redirect
}
note: I did not test my code but you should get some idea
for more information: http://laravel.com/docs/5.1/authentication
and as #mimo mention,
Your redirect url in the Services.php file has to be
localhost:8000/auth/facebook/callback
Your redirect url in the Services.php file has to be
localhost:8000/auth/facebook/callback

Laravel 5 socialize facebook login

I use auth login (out of the box). I have want to add Facebook login.
I have installed Socialize package, and In Auth/AuthController I added method fb:
public function fb()
{
return \Socialize::with('facebook')->redirect();
}
When I call http://ip/auth/fb its redirect me to http://ip/auth/login#=
Please help
First you need to create the FB project and you will have the client_id (App ID) and secret_key (App secret)
In your services configuration file: config/services.php you need to specify the facebook key like this:
'facebook' => [
'client_id' => 'client_id from fb',
'client_secret' => 'secret_key from fb',
'redirect' => 'http://your_site/your_fb_login_ok_path',
],
then you create the route:
Route::get('your_fb_login_ok_path', function ($facebook = "facebook")
{
// Get the provider instance
$provider = Socialize::with($facebook);
// Check, if the user authorised previously.
// If so, get the User instance with all data,
// else redirect to the provider auth screen.
if (Input::has('code'))
{
$user = $provider->user();
return var_dump($user);
} else {
return $provider->redirect();
}
});
This should do it.
Then remember to add this URL to your facebook redirect: http://your_site/your_fb_login_ok_path
That is the URL that FB will redirect you to after successful login.
There are a number of possibilities
You may have set the routes wrong
The Facebook Redirect Url you specified might be wrong