aladin's avatar

Socialite authentication error

Hello, I have created a Laravel application and am trying to leverage the Google socialite authentication. I have defined the APP_URL and SESSION_DOMAIN configurations to each point to www.mywebsite.com and mywebsite.com respectively. In addition, the CLIENT_ID, CLIENT_SECRET and CLIENT_REDIRECT have also been configured. My GoogleAuthController class has two function (1) redirectToGoogle() and (2) handleGoogleCallback(Request $request). The web.xml routes have also been defined.

[A] What works: if I redirect to Google as follows: return Socialite::driver('google')->stateless()->setScopes(['openid', 'email'])->redirect(); and handle the callback as follows: $user = Socialite::driver('google')->stateless()->user();, authentication works but with limited user information (ex: no avatar and no name... just email).

[B] What doesn't work - and which I'm trying to solve: (1) return Socialite::driver('google')->redirect(); (in redirectToGoogle()) (2)$user = Socialite::driver('google')->user(); (in handleGoogleCallback(Request $request))

The error that I get is: Laravel\Socialite\Two\InvalidStateException I should note that both [A] and [B] work fine on my dev machine (localhost) but [B] fails on production (www.mysite.com).

I've spent a number of hours debugging this and am hitting a bit of a wall. Any thoughts would be much appreciated.

Server: Linux with php 8.1.4 (Laravel 9)

0 likes
6 replies
aladin's avatar

@jlrdw Thanks.

Indeed, I did have a look and saw that post and the associated stackoverflow one. As you'll note from my post, the suggestions highlighted in the link you've provided (including the stackoverflow one) are already coded in my application.

For what it's worth, I've also tried to change the session driver from cookies to file to database. Read/write permissions are set correctly for the file driver (I can see the session being written) and for the database (I can see the session in the sessions table). No success.

aladin's avatar

I've continued to debug this problem. I've added the following code to the top of my Google callback function

public function handleGoogleCallback(Request $request) {
        $state = $request->get('state');
        dd("State is : " . $state);
        ... 

On localhost I get: ^ "State is : XXdRcrrYzWSkyXvtiEVMRHHAISfZ12SnL88tgyfx"

On production I get: ^ "State is : "

The mystery continues...

aladin's avatar

I've now done the following in the same Google callback to see what the request object looks like.

public function handleGoogleCallback(Request $request) {
        $state = $request->get('state');
        //dd("State is : " . $state);
        dd($request);
        ...

The output on localhost is:

  +attributes: Symfony\Component\HttpFoundation\ParameterBag {#44 ▶}
  +request: Symfony\Component\HttpFoundation\InputBag {#43 ▶}
  +query: Symfony\Component\HttpFoundation\InputBag {#50 ▼
    #parameters: array:5 [▼
      "state" => "jYCB8noVCzlWGNFvVKvX4WdgUDCcNtzpXzfSGFnf"
      "code" => "4/0AX4XfWg5p_NiN_1zOg5wjL7GjqHngCamQ75Eg8fDMNEgbzdSF6OOeqyqMoOyIuIfYONuFA"
      "scope" => "email profile openid httpsgoogleapiscom/auth/userinfo.profile httpsgoogleapiscom/auth/userinfo.email"
      "authuser" => "0"
      "prompt" => "none"
    ]
  }

On production I get this (notice the parameters array is blank):

  +attributes: Symfony\Component\HttpFoundation\ParameterBag {#44 ▶}
  +request: Symfony\Component\HttpFoundation\InputBag {#43 ▶}
  +query: Symfony\Component\HttpFoundation\InputBag {#50 ▼
    #parameters: []
  }
aladin's avatar

I think I may have found the issue, if it helps anyone (although I still have to solve this).

For whatever reason, my production server doesn't process the URL string when .profile appears in it.

With the following call back URL:

mydomaincom/auth/google/callback?state=l7mkbuECLCxl&code=4h-V50Smng&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&authuser=0&prompt=none

The query string is processed as an empty array:

^ []

However, when I remove the '.' in userinfo.profile and plug that URL in:

mydomaincom/auth/google/callback?state=l7mkbuECLCxl&code=4h-V50Smng&scope=email+profile+googleapis.com%2Fauth%2Fuserinfoprofile&authuser=0&prompt=none

The query string processed as and array with 5 elements:

^ array:5 [▼ "state" => "l7mkbuECLCxl" "code" => "4h-V50Smng" "scope" => "email profile googleapis.com/auth/userinfoprofile" "authuser" => "0" "prompt" => "none" ]

... now I need to figure out why my Apache server is doing this ...

PS: I had to remove links because laracasts is not letting me publish them (that's why the URL is mangled for mydomain.com)

aladin's avatar

Just in case anyone else is having this issue... it's fixed. Here was my solution:

    public function handleGoogleCallback(Request $request)
    {
        parse_str(parse_url($_SERVER['REQUEST_URI']['query']), $query);
        $request->mergeIfMissing($query);
        ...

Please or to participate in this conversation.