Vaunt
Vaunt

Reputation: 126

Laravel socialite - Google auth works locally but not in production: Missing required parameters code

I have a problem in my production environment with Laravel Socialite's Google auth. The error is same as on this post:

laravel socialite not working on live server, only works on local machine

but I have an Apache server and after many tries, I haven't found a solution.

Edit:

Client error: POST "https://www.googleapis.com/oauth2/v4/token" resulted in a "400 Bad Request" response:

{
 "error": "invalid_request",
 "error_description": "Missing required parameter: code"
}

Upvotes: 6

Views: 6221

Answers (5)

Sahib Khan
Sahib Khan

Reputation: 1

check first your redirect url is correct and run command:

php artisan passport:install

see this below snippet may help you

 public function socialRedirect($provider)
  {
    if ($provider === 'clever') {
      $clientId = Config::get('services.clever.client_id');
      $redirect = Config::get('services.clever.redirect');
      return redirect()->away('https://clever.com/oauth/authorize?response_type=code&redirect_uri=' . $redirect . '&client_id=' . $clientId);
    } else {
      return Socialite::driver($provider)->redirect();
    }
  }

  public function socialCallback($provider)
  {
    if ($provider === 'apple') {
      $token = app(Configuration::class)->parser()->parse(app(AppleToken::class)->generate());
      config()->set('services.apple.client_secret', $token);
    }

    $socialUser = Socialite::driver($provider)->setHttpClient(new Client(['verify' => false]))->user();

    $userIdentity = UserIdentity::where('provider_id', $socialUser->id)->where('provider_name', $provider)->first();
    $userRole = UserRole::where('slug', 'user')->first();

    if ($userIdentity) {
      // retrieve the user from users store
      $user = User::where('id', $userIdentity->user_id)->with('userRole')->with('account')->first();

      // assign access token to user
      $token = $user->createToken('social');
      $accessToken = $token->accessToken;

      $arguments = [
        'success' => true,
        'accessToken' => $accessToken,
        'expiresAt' => Carbon::parse($token->token->expires_at)->toDateTimeString(),
        'user' => json_encode($user)
      ];

      return redirect()->away(env('CLIENT_URL') . '/social/callback?' . http_build_query($arguments));
    } else {
      $user = User::where('email', $socialUser->email)->with('userRole')->with('account')->first();

      if (!($user && isset($user->id))) {
        /* $newUser = User::create([
          'fname' => $socialUser->name ?? '',
          'lname' => '',
          'email' => $socialUser->email,
          'image' => $socialUser->avatar ?? '',
          'user_role_id' => $userRole->id,
          'account_id' => 1,
          'password' => Hash::make(Str::random(40)),
          'status' => 'active',
        ]);

        $user = User::where('email', $socialUser->email)->with('userRole')->with('account')->first(); */

        $arguments = [
          'success' => false,
        ];

        return redirect()->away(env('CLIENT_URL') . '/social/callback?' . http_build_query($arguments));
      } else {
        // store user social provider info
        if ($user) {
          UserIdentity::create([
            'provider_name' => $provider,
            'provider_id' => $socialUser->id,
            'user_id' => $user->id,
          ]);
        }

        // assign passport token to user
        $token = $user->createToken('social');
        $accessToken = $token->accessToken;

        $arguments = [
          'success' => true,
          'accessToken' => $accessToken,
          'expiresAt' => Carbon::parse($token->token->expires_at)->toDateTimeString(),
          'user' => json_encode($user)
        ];

        return redirect()->away(env('CLIENT_URL') . '/social/callback?' . http_build_query($arguments));
      }
    }

Upvotes: 0

Before I knew the problem, my code was like this.

$user = Socialite::driver($provider)->stateless()->user();
$existingUser = User::where('email', $user->email)->first();

On my history error happened in method user() after stateless() the problem happens when user clicks the button cancel in sign in to process on page login with Google. As we know, after you choose your email will redirect you to a new page with option Cancel | Continue

So we apply try catch like this

try {
  $user = Socialite::driver($provider)->stateless()->user();
} catch (\Exception $e) {
  return redirect()->to('https://blablabla.id/login');
}

And it solved.

Upvotes: 0

Tatha
Tatha

Reputation: 137

See this answer if you are running an Nginx server.

Run sudo nano /etc/nginx/sites-available/default or your site config file

and fixed this line:

try_files $uri $uri/ /index.php?query_string; // wrong

to

try_files $uri $uri/ /index.php?$query_string; // fixed

Upvotes: 0

Ahmedfraije Aa
Ahmedfraije Aa

Reputation: 59

    public function redirectToProvider($driver)
{
  //  return Socialite::driver($driver)->stateless()->redirect();
    return Socialite::driver('google') ->setScopes(['openid', 'email'])

        ->redirect();
}

Upvotes: 1

Muhammad Bilal
Muhammad Bilal

Reputation: 1

This issue occurred due to profile scope in vendor\laravel\socialite\src\Two\GoogleProvider.php .

You can overcome this error by following 2 ways:

  1. Remove OR comment profile scope in vendor\laravel\socialite\src\Two\GoogleProvider.php
    protected $scopes = [
        'openid',
        'email',
    ];
  1. Initiate the Google OAUth2 stateless();
    return Socialite::driver('google')->stateless()->redirect();

Upvotes: -2

Related Questions