I am trying to add social authentication to a Laravel 5.8 API project using socialite.
When trying to handle a social provide callback, the ArgumentCountError is thrown here
Too few arguments to function App\Http\Controllers\SocialAuthController::handleProviderCallback(), 0 passed and exactly 1 expected
The error is referring to the very first line of this code block
public function handleProviderCallback($provider)
{
// retrieve social user info
$socialUser = Socialite::driver($provider)->stateless()->user();
// check if social user provider record is stored
$userSocialAccount = SocialAccount::where('provider_id', $socialUser->id)->where('provider_name', $provider)->first();
if ($userSocialAccount) {
// retrieve the user from users store
$user = User::find($userSocialAccount->user_id);
// assign access token to user
$token = $user->createToken('Pramopro')->accessToken;
// return access token & user data
return response()->json([
'token' => $token,
'user' => (new UserResource($user))
]);
} else {
// store the new user record
$user = User::create([
'name' => $socialUser->name,
'username' => $socialUser->email,
'email_verified_at' => now()
]);
...
// assign passport token to user
$token = $user->createToken('******')->accessToken;
// return response
return response()->json(['token' => $token]);
}
}
Below is how I have set up other code. Frist in env I added
GOOGLE_CLIENT_ID=******
GOOGLE_CLIENT_SECRET=*******
GOOGLE_CALLBACK_URL=https://staging.appdomain.com/api/v1/user
Then modified web.php
Auth::routes(['verify' => true]);
Route::get('/auth/{provider}', 'SocialAuthController#redirectToProvider');
Route::get('/auth/{provider}/callback', 'SocialAuthController#handleProviderCallback');
Lastly in the google app, I added the uri path where users will be redirected to after successful authentication
https://staging.appdomain.com/api/v1/user
How do I fix this?
The callback uri that user should be redirected to after successful authentication was apparently not being cached. So running php artisan route:cache fixed it.
Related
I am trying to make an API that will fetch a paticual users all data when token is passed in headers as authorization token.
I am new to Laravel and back-end I have generated token using Laravel passport.
api.php
Route::get('/{user}', [userData::class, 'get_all']);
userData.php
what I have tried is passing the id but I don't want that
public function get_all(User $user)
{
dd($user);
$user = User::where('id', $user)->first();
return response()->json([
'user' => $user,
]);
}
}
I have a problem with laravel 8 and jwt token here is a little background
I have two laravel 8 api with two databases on two different servers which I will call app 1 and app 2
and I must be able to auto connect with user 1 who has id 5 on app 1 and this same user exists but he has id 2 on app 2 but the reverse is not possible a user of app 2 cannot this connect to app 1 so sso is not possible unless I'm wrong? .
The problem is that laravel, but automatically id of the current user id 5 in the subject 'sub' of the token and I cannot overload this when I would have to give it id 2 in the ' sub 'of the token,
I manage to customize the token by adding email for example and I get the id of user 2 in the database of app 2, but each time laravel pass id of user 1, would anyone have an idea
Here is my code here at the login I will look in the DB for the user according to his email which is unique and I put in session the information that I retrieve and launch the autoload function which creates a new token
$app2User = DB::connection('mysql2')->table("users")->where('email', '=', $request->email)->pluck('id');
if (count($app2User) > 0) {
session(['app2UserId' => $app2User[0], 'app2UserEmail' => $request->email]);
$this->autoload();
} else {
log::info('is null');
}
session(['optisiloUserEmail' => $request->email]);
return $this->createNewToken($token);
Autoload function in which I put the token create in app2UserToken session to transmit it to my createNewToken function which sends me a json with the token of the current user and access_token to send to app2 for this connection
public function autoload()
{
$id = session('optisiloUserId');
$email = session('optisiloUserEmail');
$payload = JWTFactory::sub($id)->email($email)->make();
$token = JWTAuth::encode($payload);
session(['app2UserToken' => $token->get()]);
}
protected function createNewToken($token)
{
return response()->json([
'token' => $token,
'access_token' => session('optisiloUserToken'),
'token_type' => 'bearer',
'expires_in' => Auth::factory()->getTTL() * 60,
'user' => User::where('id', Auth::id())
]);
}
}
I tried this in the User model but suddenly it works on app 2 but no longer on app1 because the sub takes user id from app 2
it is the function $this->getKey() which retrieves the primaryKey or id of the current user
public function getJWTIdentifier()
{
$id = $this->getKey();
$res = User::where('id', $id)->pluck('id_user_app2')[0];
if ($res === null) {
return $this->getKey();
} else {
return $res;
}
}
how could we override the token's sub or or tell it who puts id 5 in the token and id 2 in access_token?
I am pulling User Information from an external site with external API. I have completed the user login route on the Laravel and I get the data from the controller file. There is no problem in terms of pulling and displaying data from an external user API link.
How to do token and session operation like regular Laravel user to the user logged in with external API without the database. Note that I can use the same token part of the user API token available
In addition, I don't want to transfer the information by assigning session between the controller each time the user was login. How do I assign tokens in all transactions after user login?
It comes to these controls via post method from login screen
public function loginData(Request $request)
{
$password = $request->password;
$email = $request->email;
$apiman = "Bearer {$this->accesstokenApi()}";
$client = new Client();
$response = $client->post('https://testapi.com/api/v3/Profile', [
'headers' =>
[
'cache-control' => 'no-cache',
'authorization' => $apiman,
'content-type' => 'application/json'
],
'json' =>
[
'Email' => $email,
'Password' => $password
],
]);
$data = json_decode((string) $response->getBody(), true);
if ($data['ResponseType']=="Ok") {
session()->put('token', $data);
return redirect('/user-detail');
} else {
return response()->json([
'success' => false,
'message' => 'Invalid Email or Password',
], 401);
}
}
User logged in OK . After that, what token should the machine give, or where can the session be given to that user in one place? Besides, if the user is logged in, how do I get him to see the home page instead of showing the login form again, just like in Laravel login processes ?
Maybe you can create new middleware that will check if there is a token in the session
Here is the example that you can use and adapt it based on your needs.
namespace App\Http\Middleware;
use Closure;
class Myauth
{
public function handle($request, Closure $next, $guard = null)
{
if(session()->has('token')) {
return $next($request);
} else {
return response('Unauthorized.', 401);
//OR return redirect()->guest('/');
}
}
}
I am trying to add social authentication to a laravel 5.8 API application using socialite. Following the documentation here https://laravel.com/docs/5.8/socialite#routing I created a SocialAuthController that wiill redirect the user to the provider auth page and handle the callback like this
...
use Socialite;
...
public function redirectToProvider($provider)
{
return Socialite::driver($provider)->redirect();
}
public function handleProviderCallback($provider)
{
// retrieve social user info
$socialUser = Socialite::driver($provider)->stateless()->user();
// check if social user provider record is stored
$userSocialAccount = SocialAccount::where('provider_id', $socialUser->id)->where('provider_name', $provider)->first();
if ($userSocialAccount) {
// retrieve the user from users store
$user = User::find($userSocialAccount->user_id);
// assign access token to user
$token = $user->createToken('string')->accessToken;
// return access token & user data
return response()->json([
'token' => $token,
'user' => (new UserResource($user))
]);
} else {
// store the new user record
$user = User::create([...]);
// store user social provider info
if ($user) {
SocialAccount::create([...]);
}
// assign passport token to user
$token = $user->createToken('string')->accessToken;
$newUser = new UserResource($user);
$responseMessage = 'Successfully Registered.';
$responseStatus = 201;
// return response
return response()->json([
'responseMessage' => $responseMessage,
'responseStatus' => $responseStatus,
'token' => $token,
'user' => $newUser
]);
}
}
Added the routes to web.php
Route::get('/auth/{provider}', 'SocialAuthController#redirectToProvider');
Route::get('/auth/{provider}/callback', 'SocialAuthController#handleProviderCallback');
Then I set the GOOGLE_CALLBACK_URL=http://localhost:8000/api/v1/user in my env file.
When a user is successfully authenticated using email/password, they will be redirected to a dashboard that will consume the endpoint http://localhost:8000/api/v1/user. So in the google app, I set the URI that users will be redirected to after they are successfully authenticated to the same endpoint http://localhost:8000/api/v1/user
Now when a user tries to login with google, the app throws a 401 unauthenticated error.
// 20190803205528
// http://localhost:8000/api/v1/user?state=lCZ52RKuBQJX8EGhz1kiMWTUzB5yx4IZY2dYmHyJ&code=4/lgFLWpfJsUC51a9yQRh6mKjQhcM7eMoYbINluA58mYjs5NUm-yLLQARTDtfBn4fXgQx9MvOIlclrCeARG0NC7L8&scope=email+profile+openid+https://www.googleapis.com/auth/userinfo.profile+https://www.googleapis.com/auth/userinfo.email&authuser=0&session_state=359516252b9d6dadaae740d0d704580aa1940f1d..10ea&prompt=none
{
"responseMessage": "Unauthenticated",
"responseStatus": 401
}
If I change the URI where google authenticated users should be redirect to like this GOOGLE_CALLBACK_URL=http://localhost:8000/auth/google/callback the social user information is returned.
So how should I be doing it. I have been on this for a couple of days now.
That is because you haven't put authorization in your header with your request.
you don't need to redirect user if you are working with token, your app should be a spa project, so you will redirect him from your side using js frameworks.
You need to send Authorization in your headers plus you need to specify it with your token which you returned it in your response like this:
jQuery.ajaxSetup({
headers: {
'Authorization': 'Bearer '+token
}
});
or if you are using axios
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
I have asked this question already but still I didn't get an answer.
How to login using Github, Facebook, Gmail and Twitter in Laravel 5.1?
auth not working
I am able to store data from gmail, github in the database.
Controller
if (Auth::attempt(['email' => $email, 'password' => $user_id]))
{
return redirect()->intended('user/UserDashboard');
}
else
{
//here i am going to insert if user not logged in already
return redirect()->intended('user/UserDashboard');
}
My problem is if I echo any data instead of return redirect()->intended('user/UserDashboard'); then it displays. If I add redirect then it doesn't work.
I'm not entirely sure how it works when using google for oAuth, but I assume your desired flow is:
User returns from google.
Check if user already exists, otherwise create new user record.
Log user in.
Redirect to dashboard.
Assuming the above your methods would look something like this.
Controller
public function google()
{
// Redirect user to google for authentication
return Socialite::driver('google')->redirect();
// In Laravel 5.0 this would be
// return Socialize::with('google')->redirect();
}
public function googleCallback()
{
// Return from google with user object
$googleUser = Socialite::driver('google')->user();
// In Laravel 5.0 the above would be
// $user = Socialize::with('google')->user();
// If user exists, retrieve the first() record,
// otherwise create a new record
$user = User::firstOrCreate([
'user_id' => $googleUser->id,
'name' => $googleUser->name,
'password' => $googleUser->id,
'email' => $googleUser->email,
'avatar' => $googleUser->avatar
]);
// Login the user
Auth::login($user, true);
// Redirect to the dashboard
return Redirect::intended('user/UserDashboard');
}