LoginSignup
1
4

More than 1 year has passed since last update.

Laravel Sanctumでログインは成功するが、要認証APIが401 Unauthorizedエラーを返す

Last updated at Posted at 2021-04-17

問題

LaravelでAPIを作ってて、Sanctumを利用してユーザー認証を実装し、開発環境では動作しました。そこで検証環境に持って行ったところ「ログインは成功するが、そのあと認証が必要なAPIにアクセスすると『401 Unauthorized』エラーで弾かれる」という現象が発生しました。

(私の場合の)原因

  1. そもそも開発環境用の.envだけ設定してて、検証環境用の.envにSanctum周りの設定するの忘れてた
  2. 1を受けて設定したものの、.envのSANCTUM_STATEFUL_DOMAINSの記載が間違っていた

原因1に関しては「実装できた~✌」と完全に気が抜けてましたね……スーパーアホでした😅
原因2に関してはDocker上で開発してて、雑にlocalhostで設定していても動いてしまっていたので、仕様をちゃんと理解できてなかったのが原因です。

調査

.envの反映し忘れの線はすぐに当たりましたが駄目。ブラウザの開発者ツールで401しか出ず、Cookie周りも正常動作してるように見えました。「(デプロイ自動化してないので)検証環境のライブラリ自体にロガー仕込むの面倒くさい」と、ググり倒したり設定弄り回したりあがいてみましたが、これも駄目でした。
ただ調べる過程でこの記事を見かけて、どのクラスに仕込めばいいのか当たりがつきました。大変助かりました🙏

// \vendor\laravel\sanctum\src\Http\Middleware\EnsureFrontendRequestsAreStateful.php
    public static function fromFrontend($request)
    {
        $domain = $request->headers->get('referer') ?: $request->headers->get('origin');

        if (is_null($domain)) {
            return false;
        }

        $domain = Str::replaceFirst('https://', '', $domain);
        $domain = Str::replaceFirst('http://', '', $domain);
        $domain = Str::endsWith($domain, '/') ? $domain : "{$domain}/";

        $stateful = array_filter(config('sanctum.stateful', []));

        return Str::is(Collection::make($stateful)->map(function ($uri) {
            return trim($uri) . '/*';
        })->all(), $domain);
    }

メソッド名から察しがつくかと思いますが、Webブラウザからのアクセス(Session使える)か、CLIアクセス(Session使えない)かの判定ですね。
「refererあるいはorigin、SANCUM_DOMAIN_ORIGINSを加工した上で比較してるんだな」というのが分かって、Str::isも調べてようやく、SANCTUM_STATEFUL_DOMAINSに「www.」のないドメインを登録してて、$domainとマッチしてないことに気づきました。.envの他の項目とごっちゃになったか、省略可能だろうと当てずっぽうに設定した線が濃厚です😅
「www.」を含めたドメイン名を設定することで無事動きました。

感想

ググった限り、このトラブルはそこそこある上に、原因となる要素が多いんで、StackOverFlow等でも「更新後の.envちゃんと適応してる?」とか「sessionタイプをcookieにしろ(注:デフォルトのfile設定で動きます。誤解してる人の書き込みがあるので注意)」等、場当たり的なアドバイスが多いです。チェックリストの必要性を感じましたね……誰か作ってください。(怠慢)
またsession管理がファイルの場合だと書き込み権限絡みで失敗するパターンもあるみたいなんで、この問題にハマっている人はチェックしてみてください。
それと身も蓋もないですが「(検証環境とはいえ)APP_DEBUG=trueにしたらもっと早く分かったんじゃね」と今書いてて思いましたw デプロイが手作業なこと、マルウェア問題の記事を読んだ直後で、検証環境でAPP_DEBUG=trueするのに抵抗があったので、思いついても実行出来たかどうか微妙ですが……。

🙏Laravel公式ドキュメント翻訳者への支援のお願い

Laravelの公式ドキュメントの日本語版であるReaDouble.comを運営されている川瀬裕久氏が、広告収入の低下と持病の悪化のため、翻訳プロジェクトを継続することが困難になり、GitHub sponsorsを募集しています。 日本のLaravelユーザーでここを見たことない人はいないと思うので、もし恩義を感じているならば是非支援のほどお願いします。私も支援させていただいております

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4