web-dev-qa-db-ja.com

Laravel Socialite:InvalidStateException

Laravel Socialiteを使用して、WebサイトにFacebook接続ボタンを追加しています。時々、コールバックでこのエラーが発生します:

exception 'Laravel\Socialite\Two\InvalidStateException' 
in /example/vendor/laravel/socialite/src/Two/AbstractProvider.php:161

私はそれが何を意味するのか分からず、このエラーについてまだ何も発見していません。本当の問題は、それがランダムな例外であるように見えることです(それがなぜ起こるのか理解できないでください)。では、このエラーの意味とそれを回避する方法は?

Laravel 5がAbstractProvider.phpでInvalidStateExceptionを取得する と同じ問題ではないようですが、私の場合はランダムです。

47
rap-2-h

昨夜この問題に遭遇し、次の解決策で解決しました。

私の問題の詳細については、私は持っています

AbstractProvider.php行182のInvalidStateException

関数handleProviderCallback()で、Facebookログインからリダイレクトして戻る場合。それはあなたの問題と同じようです。

さらに、wwwなしでサイトを開くと問題が発生することがわかりました。 www.mysite.comでサイトを開くと、問題ありません。最初にChris Townsendの質問への回答で手がかりを得るまで、私の問題はランダムだと思います-ありがとうございます。

ソリューション

  1. Wwwルートに移動し、laravelファイルconfig/session.phpを確認します
  2. セッションセッションCookieドメインを確認するデフォルトの構成は'domain' => null,です。'domain' => 'mysite.com'を変更しました。
  3. 'php artisan cache:clear''composer dump-autoload'の後、www.mysite.commysite.comの両方から問題なくログインできます。

これらの変更が行われた後にテストするときは、ブラウザからクッキーを必ず削除してください。古いCookieでも問題が発生する可能性があります。

68
Chaochana

解決済み:

Socialite::driver('google')->stateless()->user()
40
Nguyen Phuong

tl; dr

サードパーティのサービスから返された特定のパラメータstateを読み取る必要がある場合、statelessメソッドを使用してこのチェックを回避するようにSocialiteを設定できます。

   Socialite::driver($provider)->stateless();

Socialiteはすでにこの問題を回避する準備ができていると思います。

https://github.com/laravel/socialite/blob/2.0/src/Two/AbstractProvider.php#L77

 /**
 * Indicates if the session state should be utilized.
 *
 * @var bool
 */
protected $stateless = false;

https://github.com/laravel/socialite/blob/2.0/src/Two/AbstractProvider.php#L374

/**
 * Indicates that the provider should operate as stateless.
 *
 * @return $this
 */
public function stateless()
{
    $this->stateless = true;
    return $this;
}

https://github.com/laravel/socialite/blob/2.0/src/Two/AbstractProvider.php#L222

/**
 * Determine if the current request / session has a mismatching "state".
 *
 * @return bool
 */
protected function hasInvalidState()
{
    if ($this->isStateless()) {
        return false; // <--------
    }
    $state = $this->request->getSession()->pull('state');
    return ! (strlen($state) > 0 && $this->request->input('state') === $state);
}

たとえば、stateは、Googleにデータを渡すのに非常に便利です。

パラメーター:state(任意の文字列)
応答を受信すると、アプリケーションに役立つ可能性のある状態を提供します。 Google認証サーバーはこのパラメーターを往復するため、アプリケーションは送信した値と同じ値を受け取ります。考えられる用途には、ユーザーをサイト内の正しいリソースにリダイレクトすることや、クロスサイトリクエストフォージェリの軽減が含まれます。

参照: https://developers.google.com/identity/protocols/OAuth2UserAgent#overview

10
Igor Parra

storage/framework/sessionsフォルダーのアクセス権も確認してください。

私の場合、このフォルダーは新しいLaravelプロジェクトでは空であるため、GITリポジトリーへの最初のコミット中は除外されています。その後、実稼働サーバーで手動で作成しましたが、明らかに間違ったアクセス権で作成されたため、セッションドライバーに対して書き込み可能ではありませんでした('file'に設定した場合)。

3
Greegus

ブラウザでFacebookの代わりにFacebookアプリを使用してモバイルWeb経由でログインすると、このエラーが発生しました。 Facebookアプリは、ログイン後に現在のブラウザーではなくFacebookブラウザーを使用するため、以前の状態を認識しません。

try {
    $socialite = Socialite::driver($provider)->user();
} catch (InvalidStateException $e) {
    $socialite = Socialite::driver($provider)->stateless()->user();
}
2
makhag

既存の回答のどれにも対応していない2つの主要な「落とし穴」があります。

  1. 場合によってはInvalidStateExceptionはニシンであり、真の根本原因は他のバグです。モデルの$fillable配列に新しいフィールドを追加していないことに気付くまでに、12時間かかりました。
  2. セッション状態の検証を無効にする (ここでの他の答えはあなたがしたいが、誰もがしたくないと思われるので)、$provider->user()リクエストごとに1回だけ呼び出すことができますその関数の内部hasInvalidState()を呼び出し、それが 削除 セッションからの「状態」エントリ。 $provider->user()を複数回呼び出していることに気づくまでに数時間かかりました。一度だけ呼び出して、結果を変数に保存する必要がありました。
1
Ryan

私は同じ問題を抱えていて、この問題を解決するためにキャッシュをクリアしただけでした。このコマンドを実行して、プロセスを再度開始しました。

php artisan cache:clear

この答えが誰かに役立つことを願っています。

1
AboElnouR

私の場合、Userクラスの$fillable配列のパラメーターが欠落していることが原因でした。不足しているパラメーターをすべて追加すると、正常に動作し始めました。

1
Jan Kotas

私は同様の問題がありました、私は持っています

InvalidStateException in AbstractProvider.php line 182

関数handleProviderCallback()で、Facebookログインからリダイレクトして戻るとき。それはあなたの問題と同じようです。

さらに、wwwなしでサイトを開くと、問題が発生することがわかりました。 www.mysite.comでサイトを開くと、問題ありません。最初、質問に対するクリス・タウンゼンドの回答で手がかりを得るまで、私の問題はランダムだと思います。

ソリューション

Wwwルートに移動し、laravelファイルconfig/session.phpを確認します。セッションSession Cookie Domainを確認してください。デフォルト設定は

'domain' => null,

に変更を加えました

'domain' => 'mysite.com' 

php artisan cache:clear and composer dump-autoloadの後、www.mysite.comおよびmysite.comの両方から問題なくログインできます。

これらの変更が行われた後にテストするときは、ブラウザからクッキーを必ず削除してください。古いCookieでも問題が発生する可能性があります。

それでも助けが必要な場合は、私のコードを使用できます。 2つのルートを作成し、ユーザーテーブルを更新するだけです。 Facebookのユーザーからパスワードを取得できないため、パスワードをヌル可能にすることを忘れないでください。私のコントローラーのコード:

public function redirectToProvider()
{
    return Socialize::with('facebook')->redirect();
}

public function handleProviderCallback(User $user)
{
    $money = Socialize::with('facebook')->user();

    if(User::where('email', '=', $money->email)->first()){
    $checkUser = User::where('email', '=', $money->email)->first();
    Auth::login($checkUser);
    return redirect('home');
     } 

    $user->facebook_id = $money->getId();
    $user->name = $money->getName();
    $user->email = $money->getEmail();
    $user->avatar = $money->getAvatar();
    $user->save();

    Auth::login($user);
    return redirect('home');

}
0
Itzik Ben Hutta

これは私のためにそれを解決しました
$request->session()->put('state',Str::random(40)); $user = Socialite::driver('github')->stateless()->user();

0
lacasera

モバイルでWebを開き、電話でFacebookアプリケーションによるダイアログを開いたときにのみ、同じことが起こります。

これは、Facebook APIからの応答を取得するためにFacebookアプリを開くと、Cookieが失われるためです。ステートレスになりました。次に、socialite要求を回避するために、statelessがすでに作成されているオプションを使用します。

$user = Socialite::driver($provider)->stateless()->user();

私にはうまくいきました。それがあなたを助けることを願っています

0
Quân Hoàng

ソリューションを入手-2018年11月更新

public function redirectToGoogle(Request $request)
{
    /**
     * @var GoogleProvider $googleDriver
     */
    $googleDriver = Socialite::driver("google");
    return $googleDriver->redirect();
}

public function fromGoogle(Request $request)
{
    try {
/*
Solution Starts ----
*/
        if (empty($_GET)) {
            $t = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY);
            parse_str($t, $output);
            foreach ($output as $key => $value) {
                $request->query->set($key, $value);
            }
        }
/*
Solution Ends ----
*/
        /**
         * @var GoogleProvider $googleDriver
         */
        $googleDriver = Socialite::driver("google");
        print_r($googleDriver->user());
    } catch (\Exception $e) {
        print_r($e->getMessage());
    }
0
Tarinder

SESSION DRIVERをデータベースとして無効化するだけでこれを修正しました...このドライバーを修正しようとして数時間後、ファイルドライバーは正常に機能しました...

0
insign