<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Bearer認証 - 株式会社yep</title>
	<atom:link href="https://www.ye-p.co.jp/blog_tag/bearer%E8%AA%8D%E8%A8%BC/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.ye-p.co.jp</link>
	<description>株式会社yepのコーポレートサイト</description>
	<lastBuildDate>Wed, 16 Sep 2026 06:02:04 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1</generator>

<image>
	<url>https://www.ye-p.co.jp/wp-content/uploads/2026/06/cropped-アセット-1-32x32.png</url>
	<title>Bearer認証 - 株式会社yep</title>
	<link>https://www.ye-p.co.jp</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Laravel SanctumでBasic認証とBearer認証を共存させる方法とハマりどころ</title>
		<link>https://www.ye-p.co.jp/blog/368-2</link>
		
		<dc:creator><![CDATA[kumaki]]></dc:creator>
		<pubDate>Thu, 01 May 2025 07:51:03 +0000</pubDate>
				<guid isPermaLink="false">https://www.ye-p.co.jp/blog/368-2</guid>

					<description><![CDATA[<p>Laravel SanctumでBasic認証とBearer認証を共存させる方法とハマりどころ &#160; はじめに Laravel Sanctumは、シングルページアプリケーション（SPA）、モバイルアプリケーション [&#8230;]</p>
<p>The post <a href="https://www.ye-p.co.jp/blog/368-2">Laravel SanctumでBasic認証とBearer認証を共存させる方法とハマりどころ</a> first appeared on <a href="https://www.ye-p.co.jp">株式会社yep</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Laravel SanctumでBasic認証とBearer認証を共存させる方法とハマりどころ</p>
<blockquote id="toc"><p>&nbsp;</p></blockquote>
<h2 id="62110894-f29c-49cb-8dca-85365ffa98f9" data-id="62110894-f29c-49cb-8dca-85365ffa98f9" data-toc-id="62110894-f29c-49cb-8dca-85365ffa98f9" data-pm-slice="1 1 []">はじめに</h2>
<p data-id="8f3d0319-a07a-4553-bc75-6f14b1619f1b">Laravel Sanctumは、シングルページアプリケーション（SPA）、モバイルアプリケーション、シンプルなAPIのための軽量な認証システムです。</p>
<p data-id="42575523-5428-4401-b20a-a5d5010d095d">トークンベースの認証を提供し、APIへの安全なアクセスを可能にします。Sanctumはシンプルさと使いやすさが特徴であり、複雑な認証システムを必要としないプロジェクトに最適です。</p>
<p data-id="5a5630e9-3512-467f-956f-7e199d98ea1a">本記事では、Sanctumを用いてBasic認証とBearer認証を共存させる方法を解説します。</p>
<p data-id="b19dfdb8-0a2c-4415-839c-b98a4a953cc6">Basic認証は、シンプルな認証方法として知られており、ユーザー名とパスワードを直接送信することで認証を行います。一方、Bearer認証は、トークンを用いた認証方式であり、よりセキュアなAPIアクセスを実現します。</p>
<p data-id="0659ef01-8888-46dc-992a-5fe770ea6bad">これらの認証方式には、それぞれメリット・デメリットが存在し、使い分けることでシステムのセキュリティと利便性を向上させることができます。例えば、Basic認証は実装が容易ですが、セキュリティ面ではBearer認証に劣ります。Bearer認証は、トークンを用いることでセキュリティを高めることができますが、トークンの管理が必要となります。</p>
<p data-id="fc479541-9503-410b-b10f-44590b060d2a">状況によっては、Basic認証とBearer認証を共存させる必要が生じます。例えば、開発環境ではBasic認証を用い、本番環境ではBearer認証を用いるといったケースです。本記事では、Sanctumを用いてこれらの認証方式を共存させる方法、そして実装時に発生しやすい問題とその解決策について詳しく解説します。</p>
<h3 id="9f105646-fcbb-47c5-814f-84befe348bdf" data-id="9f105646-fcbb-47c5-814f-84befe348bdf" data-toc-id="9f105646-fcbb-47c5-814f-84befe348bdf">Sanctumとは？そのメリット・デメリット</h3>
<p data-id="466398f5-5f27-4bc2-bc8f-5670e1b1f466">Laravel Sanctumは、シングルページアプリケーション（SPA）、モバイルアプリケーション、シンプルなAPIのための軽量な認証システムです。 APIトークンベースの認証システムであり、ユーザーがログインするとトークンが発行され、そのトークンを使ってAPIにアクセスできるようになります。</p>
<table data-id="c3addadb-52a5-4e4c-804a-19fbd4d00170">
<colgroup>
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="e0ebc38d-b026-468e-a5a8-1b513ef7030b">メリット</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="ea41d6a8-9f28-479e-8d75-0131e4c3adcc">説明</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="2cfb6f5f-5b35-4a84-9c74-d38725bb534b">シンプルで軽量</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="b6e632af-38b5-44c2-8eda-6a1cc446cd95">簡単に導入・設定できるため、小規模なプロジェクトに最適です。複雑な認証システムは不要な場合に、手軽に利用できます。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="fa5d86f8-e818-4241-b3fa-9ae57b4ff77b">APIトークンベース</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="849efc7f-4a27-4e51-a220-32f1bf0cf02b">API認証に特化しており、セキュリティを高めつつ、SPAやモバイルアプリとの連携をスムーズにします。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="1c2fad3e-953d-4607-8ace-6e7479e11c1c">複数デバイスへの対応</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="5fd669ee-de8b-43ae-947c-e05fd584af41">一つのアカウントで複数のデバイスにログインし、それぞれのデバイスにトークンを発行できます。</p>
</td>
</tr>
</tbody>
</table>
<table data-id="39370cfa-f326-4332-b358-966ead735217">
<colgroup>
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="b994ff22-e3ff-4591-9778-793b7a97f68e">デメリット</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="8b16e8b8-d557-414b-b867-464cc2f5d82e">説明</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="eb497d00-3775-43f3-bc17-fb1457b55690">大規模システムには不向き</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="471d6bb4-82b0-430c-922d-f08c5299e7a9">シンプルさが故に、複雑な権限管理や多要素認証には対応していません。より高度な認証が必要な場合は、他の認証システムを検討する必要があります。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="e49a850f-9a49-40dc-bd1f-c7fc0c17357e">SPAとAPIの同一ドメイン想定</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="8725d713-1bd3-4780-93c3-804c490eb419">Sanctumは、SPAとAPIが同一ドメインで動作することを前提としています。クロスドメインの場合は追加の設定が必要になります。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="a3b7de24-1d8d-468c-88d1-fa2c1273f202">OAuthのような標準規格ではない</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="9366e31f-d6a9-4d67-817e-c424557aa5c2">Sanctum独自の仕組みであるため、OAuthのような汎用性はありません。OAuthが必要な場合は、Passportなどのライブラリを使用するべきです。</p>
</td>
</tr>
</tbody>
</table>
<h3 id="72ecb12d-68f4-4a72-b66b-8225c3cd160a" data-id="72ecb12d-68f4-4a72-b66b-8225c3cd160a" data-toc-id="72ecb12d-68f4-4a72-b66b-8225c3cd160a">Basic認証とBearer認証の使い分け、共存させる必要性</h3>
<p data-id="08b0f47a-2074-4329-af71-6f2295287e62">Basic認証とBearer認証は、それぞれ異なる特性を持つため、使い分けが必要です。Basic認証は、シンプルで実装が容易ですが、セキュリティ面ではBearer認証に劣ります。一方、Bearer認証は、トークンベースでより安全な認証方式ですが、実装が複雑になる場合があります。</p>
<table data-id="d2a8fbb2-fac1-464d-bfc2-297aa51ad6fd">
<colgroup>
<col />
<col />
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="3a8d69a4-8834-4f9e-9d43-f64edf2c6a7c">認証方式</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="71d62576-7521-44ce-b785-f1133986b1c8">メリット</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="a96a650f-a077-4a03-b6bd-ae0f3a35005c">デメリット</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="c6782871-4f93-4264-8b0a-11ded60ba841">具体的なユースケース</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="5f377815-1c73-44bf-ab69-5f83b70e5c76">Basic認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="a7e8a966-5d82-485c-8da7-46b42c05c193">シンプルで実装が容易</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="16fd382a-57b7-4b57-949a-d4ffe2eef1b1">セキュリティ面で脆弱</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="5f622784-34e9-4feb-b870-30b9ddcf0aff">開発環境、社内システム等、セキュリティ要件が低い環境</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="463e4633-f087-46d4-926f-c6647dc2e71b">Bearer認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="4154902e-57de-4ec7-a667-024f52841b5c">トークンベースでより安全</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="788245ea-77d7-4310-8d57-d3224dfed635">実装が複雑になる場合がある</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="797a56a4-2523-4164-b016-07140d9ac0a6">本番環境、外部公開API等、セキュリティ要件が高い環境</p>
</td>
</tr>
</tbody>
</table>
<p data-id="23122169-ea04-4396-a215-68edbbbc8fd2">これらの認証方式を共存させる必要性は、例えば以下のようなケースが考えられます。</p>
<ul data-id="75ed6a3e-747d-4c1c-8ef3-48c0b532c8d1">
<li>
<p data-id="ce999fb0-1088-4d5d-8f3a-41c1d7b723bf">すでにBearer認証を使用しているシステムを、Basic認証がかかっている開発環境に設置する場合。</p>
</li>
<li>
<p data-id="8c47a5d9-5ab3-4075-9a37-d9240deee1bb">セキュリティ要件の異なる複数のシステムを統合する場合。</p>
</li>
</ul>
<p data-id="2438cfeb-20b5-4bcd-9b11-18db63021ba7">このようなケースでは、それぞれの認証方式のメリットを活かしつつ、デメリットを補うために、Basic認証とBearer認証を共存させる構成が有効です。</p>
<h2 id="f1e11b6a-7771-47e4-8a85-01aeb7646962" data-id="f1e11b6a-7771-47e4-8a85-01aeb7646962" data-toc-id="f1e11b6a-7771-47e4-8a85-01aeb7646962">Sanctumの基本設定</h2>
<p data-id="b387545f-a4de-4f80-a7b1-56a55e77d4b2">Sanctumを使うための基本設定について解説します。Sanctumは、LaravelアプリケーションでSPA（Single Page Application）やモバイルアプリケーション、シンプルなAPIを認証するための軽量な認証システムです。</p>
<p data-id="ea254ca1-b27b-4971-89a7-f20b2824201c">SanctumのインストールはComposerを使って行います。</p>
<pre><code>composer require laravel/sanctum
</code></pre>
<p data-id="cf88811b-aad7-4378-be2b-c159a0e47e9b">インストールが完了したら、Sanctumの設定ファイルを公開します。</p>
<pre><code>php artisan vendor:publish --provider="LaravelSanctumSanctumServiceProvider"
</code></pre>
<p data-id="796dd10e-953f-46ef-9739-c085c582c0aa">このコマンドを実行することで、<code>config/sanctum.php</code>ファイルが作成されます。このファイルでは、Sanctumの動作をカスタマイズするための様々な設定オプションが用意されています。 特に重要なのは<code>stateful</code>の項目で、ここにSPAのURLを記載します。これにより、指定されたドメインからのリクエストは認証状態を保持するようになります。</p>
<p data-id="af87f881-255e-43b2-bc46-d60c1dc5be63">APIトークンの発行は、<code>Sanctum::personalAccessToken()</code>メソッドを使って行います。 <code>createToken</code>メソッドを呼び出すことで、指定した名前のトークンを生成できます。</p>
<table data-id="e19d3807-808b-45ef-b5c5-848570c78340">
<colgroup>
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="e51a2bcb-edb1-43b0-8731-7b316236f068">設定項目</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="a3c424f5-5e57-42d8-853d-5c4eb41baf3e">説明</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="a09fd59c-b516-4594-bfac-8f657a3bbf16">stateful</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="b42c0112-64ee-443d-8c30-c9a0f376656a">認証状態を保持するドメインを指定します。SPAの場合はここにSPAのURLを記載します。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="054142a3-87b6-4e81-b27e-ec991d9ac9d3">middleware</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="a4ab3540-b0b1-4a66-8bed-25e9faee01ff">Sanctumのミドルウェアを指定します。通常は<code>auth:sanctum</code>を使用します。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="914d2dc0-6606-4888-a5ea-e0c697bc5c6e">expiration</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="5a4f81dd-13e8-462b-bb50-17071a3d5898">トークンの有効期限を指定します。nullの場合は無期限になります。</p>
</td>
</tr>
</tbody>
</table>
<p data-id="db0cb3e1-5b03-4f3c-8056-d9fa93a5fa09">これらの設定を行うことで、Sanctumの基本的なセットアップが完了します。</p>
<h3 id="76a24394-8e04-40f8-92be-0c516dc7c81a" data-id="76a24394-8e04-40f8-92be-0c516dc7c81a" data-toc-id="76a24394-8e04-40f8-92be-0c516dc7c81a">Sanctumのインストールと設定</h3>
<p data-id="3aa730c8-96c6-4818-940e-c6a9f4bcaf00">Sanctumは、LaravelアプリケーションにシンプルなAPI認証を提供するための公式パッケージです。SPA（Single Page Application）やモバイルアプリケーション、シンプルなトークンベースのAPIに最適です。まずは、Composerを使用してSanctumをインストールします。</p>
<pre><code>composer require laravel/sanctum
</code></pre>
<p data-id="bb380294-4927-468e-8ea4-f50a81b1ca84">インストールが完了したら、Sanctumの設定ファイルを公開します。</p>
<pre><code>php artisan vendor:publish --provider="LaravelSanctumSanctumServiceProvider"
</code></pre>
<p data-id="565bf9fc-675c-4963-a234-418044aa6bf9">これにより、<code>config/sanctum.php</code>ファイルが作成されます。通常、デフォルト設定で問題ありませんが、必要に応じて<code>stateful</code>ガードの設定やAPIトークンの有効期限などを変更できます。</p>
<p data-id="469b779c-ef72-43b3-91d0-a87b1326183a">データベースマイグレーションを実行して、Sanctumに必要なテーブルを作成します。</p>
<pre><code>php artisan migrate
</code></pre>
<p data-id="3ab560ec-8d10-4b08-a037-04ed58ba87d3">SPA認証を使用する場合は、<code>app/Http/Kernel.php</code>ファイルの<code>api</code>ミドルウェアグループに<code>LaravelSanctumHttpMiddlewareEnsureFrontendRequestsAreStateful::class</code>ミドルウェアを追加します。</p>
<pre><code class="language-php">'api' =&gt; [
    // ... other middleware
    LaravelSanctumHttpMiddlewareEnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    IlluminateRoutingMiddlewareSubstituteBindings::class,
],
</code></pre>
<p data-id="a31fddb7-a4e5-4aa6-b618-c3f0bb86495f"><code>stateful</code>ガードに保護されたルートへのリクエストは、Sanctumが発行したAPIトークンを使って認証されます。</p>
<h3 id="9c8ce0a4-eaf6-464b-9c15-529e7ab61e1d" data-id="9c8ce0a4-eaf6-464b-9c15-529e7ab61e1d" data-toc-id="9c8ce0a4-eaf6-464b-9c15-529e7ab61e1d">SPA認証の設定</h3>
<p data-id="f378a1ea-5138-4786-929a-d989a9a2f450">Sanctumは、SPA（Single Page Application）の認証も簡単に実装できます。SPAはフロントエンドとバックエンドが分離されているため、APIトークンを用いた認証が一般的です。Sanctumでは、このAPIトークンを発行・管理する機能を提供しています。</p>
<p data-id="d72c28d8-ba21-46b9-952e-fe21f2c9cebd">SanctumでSPA認証を設定するには、まず<code>config/sanctum.php</code>ファイルの<code>stateful</code>配列に、SPAのドメインを追加します。例えば、SPAのURLが<code>http://spa.example.com</code>の場合は、以下のように設定します。</p>
<pre><code>'stateful' =&gt; [
    'spa.example.com',
],
</code></pre>
<p data-id="889801ef-3cc2-45b9-86bd-13add15d52b4">この設定により、指定されたドメインからのリクエストは、Cookieに保存されたセッションIDを使用して認証されます。つまり、SPAからAPIリクエストを送信する際に、<code>Authorization</code>ヘッダにBearerトークンを付与する必要はありません。Sanctumが自動的にCookieからセッションIDを読み取り、認証を行います。</p>
<p data-id="ff65fce8-d1eb-4da5-b4ed-2534b9938cfc">また、CORS（Cross-Origin Resource Sharing）の設定も必要です。<code>config/cors.php</code>ファイルの<code>paths</code>配列に、APIのパスを追加します。例えば、APIのパスが<code>/api/*</code>の場合は、以下のように設定します。</p>
<pre><code>'paths' =&gt; ['api/*'],
</code></pre>
<p data-id="b15ffae6-1ff6-412a-a71f-014cab430f1c">この設定により、指定されたパスへのリクエストに対して、CORSヘッダが付与されます。これにより、SPAからAPIにアクセスできるようになります。</p>
<h3 id="dfc3af6c-769a-4ba4-af25-fb47da835f87" data-id="dfc3af6c-769a-4ba4-af25-fb47da835f87" data-toc-id="dfc3af6c-769a-4ba4-af25-fb47da835f87">APIトークンの発行</h3>
<p data-id="47867c6b-13c6-4b67-92a5-ca7cb7bedcef">Sanctumでは、APIトークンを発行することで、SPA(Single Page Application)やモバイルアプリケーションなどから安全にAPIにアクセスできます。トークンは、ユーザーごとに発行され、特定の有効期限を持つことができます。</p>
<p data-id="2cf8d284-70d7-48fd-8fb8-f363e1e1d23d">Laravel SanctumでAPIトークンを発行するには、主に2つの方法があります。</p>
<ol data-id="3062be87-0bf9-4fa5-a8c0-f256fdc0cbee">
<li>
<p data-id="becdbffc-3487-4124-947d-bb7796dfc5ea"><code>createToken</code>メソッドを使う方法</p>
<p data-id="e975cf97-2e2e-44d8-97e8-187016ec8595"><code>createToken</code>メソッドは、<code>User</code>モデルにSanctumが追加するメソッドです。<br />
このメソッドを呼び出すことで、指定した名前のトークンを発行できます。<br />
例えば、<code>web</code>という名前のトークンを発行するには、以下のように記述します。</p>
<pre><code class="language-php">$token = $user-&gt;createToken('web')-&gt;plainTextToken;
</code></pre>
<p data-id="da4398a5-9c10-4340-9837-db55a41c7220"><code>plainTextToken</code>プロパティにアクセスすることで、プレーンテキスト形式のトークンを取得できます。このトークンをクライアントに返却し、クライアントは<code>Authorization</code>ヘッダーに<code>Bearer {token}</code>の形式で設定してAPIリクエストを送信します。</p>
</li>
<li>
<p data-id="88ca2721-2f54-4774-94c3-c751831a13ad"><code>personal-access-tokens</code>テーブルを直接操作する方法</p>
<p data-id="c11e58ab-c2fa-486a-a904-10154f625978"><code>createToken</code>メソッドの内部では、<code>personal-access-tokens</code>テーブルにトークン情報が保存されます。<br />
このテーブルを直接操作してトークンを発行することも可能です。<br />
ただし、通常は<code>createToken</code>メソッドを使用する方が簡単で安全です。</p>
</li>
</ol>
<table data-id="f3289c24-b253-4ff4-8dd1-17005bad23f8">
<colgroup>
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="f7c29e58-4965-4061-9d26-4685d76b84f2">方法</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="d6d4e907-fd1b-4db6-b230-36e3987a7041">説明</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="07ef26fe-7c8c-4ed2-8bf9-0495f510001f"><code>createToken</code>メソッド</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="f9135c6d-0f6f-470f-a789-ce65086006f8"><code>User</code>モデルにSanctumが追加するメソッド。シンプルにトークンを発行できる。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="b7ac403e-3894-4ba5-ad6d-a438a07a4134"><code>personal-access-tokens</code>テーブル</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="cac4dd9f-c7bf-425e-baae-d54e3a6a14c4">テーブルを直接操作する方法。<code>createToken</code>メソッドよりも複雑だが、柔軟な操作が可能。</p>
</td>
</tr>
</tbody>
</table>
<h2 id="402c6124-6ae6-4728-b00b-c6d77b035974" data-id="402c6124-6ae6-4728-b00b-c6d77b035974" data-toc-id="402c6124-6ae6-4728-b00b-c6d77b035974">Basic認証の実装</h2>
<p data-id="22c58932-5d57-4720-9db6-6e6a6c8da8a0">SanctumでBasic認証を実装する場合、ミドルウェア<code>auth:sanctum</code>はそのままではBearer認証を想定しているため、工夫が必要です。Basic認証を特定のルートに適用するには、<code>auth.basic</code>ミドルウェアを使用します。</p>
<p data-id="bcf56e16-3e75-4eb4-b5cb-bafd89469d15"><code>auth:sanctum</code>ミドルウェアは、APIルートでBearerトークンによる認証を期待します。そのため、Basic認証をSanctumと共存させる場合、適用範囲を適切に制御する必要があります。</p>
<table data-id="c266c7c5-00e8-42eb-9731-7238349306c1">
<colgroup>
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="5490aa05-4539-4fa4-bcd0-4fcbcdd80037">ミドルウェア</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="a6c5bad1-fa6d-46c5-af1c-aff52911995d">説明</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="2c52fb90-7936-42bf-8c2e-4978b409c620"><code>auth:sanctum</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="463b09fc-c64f-4ee1-8b37-c6b9857fc941">Bearerトークンによる認証</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="af622c0c-85cb-45e7-918f-18640e7b9b6c"><code>auth.basic</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="55cac99e-87b2-47d8-b6fd-9ee9479382de">Basic認証</p>
</td>
</tr>
</tbody>
</table>
<p data-id="5ca74b02-1cef-47b2-a6ac-7b7e653fb8ef">Basic認証を使用したいルートの<code>routes/api.php</code>に、以下のように<code>auth.basic</code>ミドルウェアを適用します。</p>
<pre><code class="language-php">Route::middleware('auth.basic')-&gt;group(function () {
    Route::get('/basic-auth-route', function (Request $request) {
        // Basic認証が必要な処理
        return $request-&gt;user();
    });
});
</code></pre>
<p data-id="06bd661c-520e-41a1-a716-0212e7858c6c">この設定により、<code>/basic-auth-route</code>へのアクセスにはBasic認証が要求されます。<code>auth.basic</code>ミドルウェアは、HTTPリクエストヘッダーの<code>Authorization</code>フィールドからBasic認証の資格情報を取得し、ユーザーを認証します。</p>
<h3 id="95507840-7ed6-484a-991a-3ec429c5d4cf" data-id="95507840-7ed6-484a-991a-3ec429c5d4cf" data-toc-id="95507840-7ed6-484a-991a-3ec429c5d4cf">ミドルウェア`auth:sanctum`の挙動とBasic認証</h3>
<p data-id="ae32a1ff-423c-46c1-a4b4-0c9118ff080b">Sanctumは、デフォルトではAPIトークンによるBearer認証を想定しています。しかし、<code>auth:sanctum</code>ミドルウェアは、Basic認証にも対応しています。<code>auth:sanctum</code>ミドルウェアが有効なルートにアクセスがあった場合、Sanctumは以下の手順で認証を試みます。</p>
<ol data-id="d24a1167-1efa-4cad-8323-15489c46f5b0">
<li>
<p data-id="c9960379-ae65-4993-a057-9e60b8a5afd0">Authorizationヘッダーを確認し、BearerトークンがあればBearer認証を試みます。</p>
</li>
<li>
<p data-id="21473c11-879b-434e-bf8d-cb64f787fedd">Bearerトークンがない場合、PHPの組み込み認証機能を使ってBasic認証を試みます。</p>
</li>
<li>
<p data-id="29d38e37-c9f2-4a3f-99da-5c3ea734cbad">Basic認証が成功すると、Sanctumは一時的なAPIトークンを発行し、そのトークンを使って認証を行います。このトークンはリクエストの間だけ有効で、保存はされません。</p>
</li>
</ol>
<p data-id="30db3542-7161-458a-bb1c-81ecf38e8eec">つまり、<code>auth:sanctum</code>ミドルウェアを適用するだけで、Bearer認証とBasic認証の両方に対応できます。</p>
<table data-id="8c6b2176-5657-48eb-ab49-bed867768290">
<colgroup>
<col />
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="7179c516-f325-4618-8e6c-0f30333f8046">認証方式</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="b73a5e21-0b56-4da6-8d1f-00df7262454a">トークン</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="f042fb16-fd4d-4e47-ab96-5a44ddba06df">有効期限</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="7c3665f6-ed7c-4f79-a4fd-bb71338f462b">Bearer認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="6ace105a-ef9c-4e5d-bec2-59ad81109391">APIトークン</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="39b8bc3f-d525-4440-9e80-28381ad3551c">設定による</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="6f34436a-1dae-47ea-bbcd-d4f311947b10">Basic認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="cbf05554-d796-454f-b7da-0c97dac7fecc">一時的なAPIトークン</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="98cfc286-4f49-4600-83f2-aadc0f9829a5">リクエストの間だけ</p>
</td>
</tr>
</tbody>
</table>
<p data-id="98a9053a-9529-495e-86a1-23e3144fa0fc">この挙動を利用することで、<code>auth:sanctum</code>ミドルウェア一つで両方の認証方式を扱えるので、APIクライアントとブラウザからのアクセスが混在するアプリケーションで特に便利です。</p>
<h3 id="18e4287f-7194-40ae-bf30-d3227327774b" data-id="18e4287f-7194-40ae-bf30-d3227327774b" data-toc-id="18e4287f-7194-40ae-bf30-d3227327774b">特定ルートへのBasic認証適用</h3>
<p data-id="190b0151-09e1-405a-8458-2bfa04454ac0">Basic認証を特定のルートに適用するには、ミドルウェアを活用します。<code>routes/web.php</code>や<code>routes/api.php</code>で、<code>middleware</code>メソッドを使って適用したいルートにBasic認証を指定します。</p>
<p data-id="d676b78c-82bf-4c93-b798-47b6ccc22003">例えば、<code>/admin</code>以下のルート全てにBasic認証をかけたい場合は、以下のように記述します。</p>
<pre><code class="language-php">Route::prefix('admin')-&gt;middleware('auth.basic')-&gt;group(function () {
    Route::get('/dashboard', function () {
        return view('admin.dashboard');
    });

     // その他のadminルート
});
</code></pre>
<p data-id="b882b626-7793-4488-bd8b-dfe4a8f489b3"><code>auth.basic</code>ミドルウェアは、デフォルトで<code>name</code>カラムを利用して認証を行います。<code>users</code>テーブル以外のテーブルを利用する場合や、別のカラムを利用したい場合は、<code>config/auth.php</code>の<code>guards</code>配列にある<code>basic</code>の設定を変更する必要があります。例えば、<code>admins</code>テーブルの<code>email</code>カラムを利用したい場合は、以下のように設定します。</p>
<pre><code class="language-php">'guards' =&gt; [
    'basic' =&gt; [
        'driver' =&gt; 'basic',
        'provider' =&gt; 'admins', // adminsプロバイダを指定
    ],
// ...
],
'providers' =&gt; [
    'admins' =&gt; [
        'driver' =&gt; 'eloquent',
        'model' =&gt; AppModelsAdmin::class, // Adminモデルを指定
    ],
// ...
]
</code></pre>
<p data-id="471bddb9-e70a-42ae-a610-b29aee35f03b">上記のように設定することで、<code>auth.basic</code>ミドルウェアは<code>admins</code>テーブルの<code>email</code>カラムを利用して認証を行うようになります。</p>
<h2 id="78a7bc7c-888e-4c00-9fa1-3a22b972cdce" data-id="78a7bc7c-888e-4c00-9fa1-3a22b972cdce" data-toc-id="78a7bc7c-888e-4c00-9fa1-3a22b972cdce">Bearer認証の実装(SPA)</h2>
<p data-id="8f8263df-95f2-4b1b-a6a3-2cf492d5cef1">Sanctumを利用したSPA(Single Page Application)におけるBearer認証の実装方法について解説します。SanctumはAPIトークンを発行し、このトークンを利用して認証を行います。クライアントサイド（ブラウザ）からAPIリクエストを送信する際に、<code>Authorization</code>ヘッダに<code>Bearer &lt;トークン&gt;</code>の形式でトークンを含めることでBearer認証が実現できます。</p>
<table data-id="12857301-ac01-4c1e-9a0e-b247371eb86e">
<colgroup>
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="be263f72-584b-4dec-993e-f5366c4fb00e">項目</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="e0a7dd28-6979-41c7-a77f-0f7b36382a08">説明</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="ec5e7a41-3e41-4d4c-bf6e-ecf86b6137d4">トークン取得</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="c557e2a1-fdad-484c-b4b3-bf3b419beb60">Laravel Sanctumは、ログイン時にAPIトークンを自動的に生成し、レスポンスに含めて返します。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="50532593-47e9-482c-a57d-9ee914fce1fa">トークン設定</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="160d4ca2-aec8-48b8-b8c4-cb3193bcfed1">クライアントサイドでは、このトークンを安全に保存（例：ローカルストレージ、HTTP only Cookie）する必要があります。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="6e3ee348-af9d-4341-8af4-6bd38e13cf7d">リクエスト送信</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="5ba214e2-a194-415b-ac04-a93d0c98aeee">AxiosなどのJavaScriptライブラリを使用してAPIリクエストを送信する際、<code>Authorization</code>ヘッダに<code>Bearer &lt;トークン&gt;</code>を設定します。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="e35a6d7f-9370-4f2c-9cd3-7db53781c3aa">認証処理</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="4a53a91b-2441-4b66-b394-a1bdfac01e27">サーバーサイドでは、Sanctumミドルウェアが<code>Authorization</code>ヘッダからトークンを抽出し、ユーザーを認証します。</p>
</td>
</tr>
</tbody>
</table>
<p data-id="f85314e2-25fd-46f7-b33c-c65d06ab6f6a">JavaScript(Axios)を用いたBearer認証の実装例を以下に示します。</p>
<pre><code class="language-javascript">axios.get('/api/user', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
})
.then(response =&gt; {
  // 認証成功時の処理
  console.log(response.data);
})
.catch(error =&gt; {
  // 認証失敗時の処理
  console.error(error);
});
</code></pre>
<p data-id="d731ee6d-03e0-4951-92a3-f433a9e525d2">上記のように、リクエストヘッダーに<code>Authorization: Bearer &lt;トークン&gt;</code>を含めることで、SanctumによるBearer認証が有効になります。トークンはログイン時に取得し、安全に保管するようにしてください。</p>
<h3 id="1ab2c3ee-cde0-460e-a1d6-d6ad7cef5c98" data-id="1ab2c3ee-cde0-460e-a1d6-d6ad7cef5c98" data-toc-id="1ab2c3ee-cde0-460e-a1d6-d6ad7cef5c98">Sanctumが発行するAPIトークンの利用方法</h3>
<p data-id="27d722a7-afe8-47ee-ae8f-361bedb0df38">Sanctumでは、<code>createToken</code>メソッドを用いてAPIトークンを発行します。発行されたトークンは、クライアント側で安全に保管する必要があります。</p>
<table data-id="29f3b383-5e17-464b-909b-fa07e70a74ab">
<colgroup>
<col />
<col />
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="2c90a918-12dd-4dcb-9568-2ed447480ca1">ストレージ</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="e4675592-ada4-4f73-889c-a31ea3332edb">メリット</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="694aa925-870b-4020-a8f6-acd88816d05b">デメリット</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="88076041-7b16-4e7e-8a36-93e3ace9720a">備考</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="17783b95-0768-44ab-b6f6-8de4dc1ec353">ローカルストレージ</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="65c17c8f-d90b-419c-b52f-3d26c2f487cd">JavaScriptから簡単にアクセス可能</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="051d765f-b121-4a39-9218-987d2c674ad2">XSSの脆弱性がある場合、トークンが盗まれるリスクが高い</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="5f8b4f1e-8af4-4c83-b3d8-2fac76d501c4">セキュリティ対策を十分に行う必要がある</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="3d1fbcb3-c6a1-490c-aaef-bb3de2a6b6ec">クッキー</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="40ed87ba-5213-43e6-a157-9718f2214f54">HttpOnly属性を設定することで、JavaScriptからのアクセスを制限できるため、XSS攻撃に対して安全</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="f0bb12e9-7901-416a-a5f8-2fbb4b39eb76">CSRF攻撃への対策が必要</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="65d230b2-a5e6-4dbd-9da9-783591cd78c5">セキュアな環境で利用するのが望ましい</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="7e4829c9-c817-4192-8986-833c4b09b702">セッションストレージ</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="cbd00226-11bb-4679-acf9-376677ffc986">ブラウザを閉じるとトークンが削除されるため、セキュリティが高い</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="5206f473-0fcd-402a-97d3-d6af02a2d975">トークンの有効期限がブラウザのセッションに限定される</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="91d135c9-3fdd-44a4-bdae-21f815d5086f">短期的なアクセスに適している</p>
</td>
</tr>
</tbody>
</table>
<p data-id="f5fdc92d-6dd6-4f4b-a558-8b45d58cddcc">トークンは、リクエストヘッダーの<code>Authorization</code>フィールドに<code>Bearer</code>スキームで付与してAPIリクエストを行います。</p>
<p data-id="f710ca47-49c6-4a5b-b060-a55cd17c7ddc">例：</p>
<pre><code>Authorization: Bearer &lt;your_api_token&gt;
</code></pre>
<p data-id="bcec0f62-5b85-4b02-8bb8-0191c99049ad">JavaScriptのAxiosライブラリを使用する場合、以下のように実装できます。</p>
<pre><code class="language-javascript">axios.get('/api/user', {
  headers: {
    'Authorization': `Bearer ${your_api_token}`
  }
});
</code></pre>
<p data-id="fedf4410-bf73-4dff-9266-be80a58741cc">このようにトークンを付与することで、Sanctumは<code>personal_access_tokens</code>テーブルに保存されているトークンと比較し、認証を行います。</p>
<h3 id="df7e221e-c73c-4dac-9d59-befd7aee435d" data-id="df7e221e-c73c-4dac-9d59-befd7aee435d" data-toc-id="df7e221e-c73c-4dac-9d59-befd7aee435d">JavaScript(Axios等)を用いたBearer認証の実装例</h3>
<p data-id="c1efa692-bdef-4966-8c4b-21dda9104ffc">Axiosを使ってLaravel Sanctumで保護されたAPIエンドポイントにリクエストを送信する例を以下に示します。</p>
<pre><code class="language-javascript">// Axiosのインスタンスを作成します。
const axiosInstance = axios.create({
  baseURL: '/api', // APIのベースURLを設定
  timeout: 5000, // タイムアウト時間を設定
});

// リクエストインターセプターを追加します。
axiosInstance.interceptors.request.use(
  (config) =&gt; {
    // ローカルストレージからトークンを取得します。
    const token = localStorage.getItem('sanctum_token');

    // トークンが存在する場合、AuthorizationヘッダーにBearerトークンを追加します。
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    return config;
  },
  (error) =&gt; {
    // エラーハンドリング
    return Promise.reject(error);
  }
);

// APIリクエストの例
axiosInstance.get('/user')
  .then(response =&gt; {
    console.log(response.data);
  })
  .catch(error =&gt; {
    console.error(error);
  });

</code></pre>
<p data-id="2f967c55-01ff-4ca8-ab83-29302d111b1d">この例では、Axiosのインターセプターを使用して、すべてのリクエストにBearerトークンを自動的に追加しています。<code>localStorage</code>からトークンを取得し、<code>Authorization</code>ヘッダーに<code>Bearer ${token}</code>の形式で設定しています。リクエスト前にトークンの有無を確認することで、トークンがない場合のエラーを回避できます。</p>
<h2 id="654fc50b-d2cd-4ab7-8df0-35e1a1085396" data-id="654fc50b-d2cd-4ab7-8df0-35e1a1085396" data-toc-id="654fc50b-d2cd-4ab7-8df0-35e1a1085396">両認証の共存設定とルーティング</h2>
<p data-id="845f0733-5117-4211-bf8e-ba89c25c3d81">この章では、Basic認証とBearer認証をどのように共存させるのか、ルーティングの設定方法を含めて解説します。</p>
<p data-id="ade7d9ba-645e-4482-aafb-cd4f63763a3b">Laravel Sanctumでは、ミドルウェアの適用範囲を指定することで、Basic認証とBearer認証を共存させることができます。<br />
<code>auth:sanctum</code>ミドルウェアをAPIルート全体に適用し、Basic認証が必要なルートには<code>auth.basic</code>ミドルウェアを追加で適用します。</p>
<p data-id="3db2bec7-f9fa-4730-a93f-f99e3812f8c3">Sanctumは、<code>stateful</code>ガードと<code>stateless</code>ガードを使い分けます。SPA認証では<code>stateful</code>ガードを、APIトークン認証では<code>stateless</code>ガードを用います。<code>auth:sanctum</code>ミドルウェアはデフォルトで<code>stateful</code>ガードを利用するため、Basic認証とSPA認証を共存させることができます。</p>
<table data-id="ea759566-7715-4fc6-a78b-22ec5574eff9">
<colgroup>
<col />
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="6b76aa44-fff0-46bd-801a-9a8654e20700">ガード</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="29cbe041-463c-485e-8016-ef489c551920">認証方式</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="ba3ab868-6e6b-44bc-84cc-0b2e094fb8e8">説明</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="d62a552b-7ce5-41aa-9b0d-95b065fd4a2f"><code>stateful</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="67f8b20e-07a9-4d85-b66a-61b594664a72">セッション/Cookie, Basic認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="01371139-58c7-4764-8a89-4152d5368b09">セッションやCookieを利用した認証、またはBasic認証</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="458b9b18-f4c4-4f44-b977-0084c1d1e4a1"><code>stateless</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="5f338d36-c37f-4470-a44b-9f1089fa9b85">APIトークン</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="33f73047-5e4b-4cf7-877f-637289204032">APIトークンを利用した認証</p>
</td>
</tr>
</tbody>
</table>
<p data-id="cea80841-756d-4cf2-9198-d9b3b34d0a6a">認証方式によってルーティングを設計することで、セキュリティを向上させ、APIの利用を適切に管理できます。たとえば、管理画面へのアクセスにはBasic認証を、APIアクセスにはBearer認証を用いるといった設計が可能です。</p>
<h3 id="f12755e4-d8a2-466b-86cf-a9270ba4e3e6" data-id="f12755e4-d8a2-466b-86cf-a9270ba4e3e6" data-toc-id="f12755e4-d8a2-466b-86cf-a9270ba4e3e6">ミドルウェアの適用範囲指定による共存設定</h3>
<p data-id="098e5194-ff8f-4abb-8fe8-165c0d32bbf5">Sanctumを利用する場合、Basic認証とBearer認証を共存させることができます。<br />
これは、ミドルウェアの適用範囲を適切に指定することで実現できます。<br />
例えば、APIルートの一部をBasic認証、他の部分をBearer認証で保護することができます。</p>
<table data-id="60805480-9773-4c88-824d-693d5eb4fabf">
<colgroup>
<col />
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="a81e8253-eaca-4d3c-b3f2-0c5b428effbe">認証方式</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="32dee524-c540-4823-9572-a42ace53bb4f">ミドルウェア</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="992e1522-2431-43a0-81b7-888934985981">適用範囲</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="46c45985-8052-4411-86ce-12041f394398">Basic認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="e0830db3-43e7-465d-acf9-2b8b0e110eb4"><code>auth:sanctum</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="7c512cbc-2d89-4b82-9df8-5911705ed04e"><code>/api/basic</code> 以下のルート</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="289d5b85-404b-4e0b-88eb-7f9fd495aed6">Bearer認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="9bd05925-d6cb-41df-91a2-70c1b7a6f883"><code>auth:sanctum</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="a799edd4-1dbc-4953-bf3c-50605ae36d7e"><code>/api/spa</code> 以下のルート</p>
</td>
</tr>
</tbody>
</table>
<p data-id="ce175687-7aad-4fbe-b096-6143f2b40444">上記のように設定することで、クライアントは <code>/api/basic</code> 以下のAPIへアクセスする際にはBasic認証を、<code>/api/spa</code> 以下のAPIへアクセスする際にはBearer認証を使用する必要があります。<br />
<code>auth:sanctum</code> ミドルウェアは、リクエストヘッダーに含まれる認証情報に基づいて適切な認証方式を自動的に選択します。<br />
つまり、Basic認証とBearer認証のどちらのリクエストにも対応可能です。<br />
これにより、APIの利用状況に応じて柔軟に認証方式を使い分けることができます。</p>
<h3 id="5cc32878-81de-4e15-86b3-fbcb79414214" data-id="5cc32878-81de-4e15-86b3-fbcb79414214" data-toc-id="5cc32878-81de-4e15-86b3-fbcb79414214">stateful guardとstateless guard</h3>
<p data-id="5ee197aa-9953-4f0a-8336-a38bebb49536">Sanctumは、statefulな認証とstatelessな認証の両方をサポートしています。</p>
<p data-id="052f1f78-6c0f-47c8-b60a-97241f44d53b">stateful guard（セッション認証）は、従来のWebアプリケーションでよく使われる認証方式です。ユーザーがログインすると、サーバー側にセッション情報が保存され、以降のリクエストではそのセッション情報を使って認証を行います。Sanctumでは、<code>web</code>ガードがこのstateful guardに該当します。SPA認証においては、<code>web</code>ミドルウェアで守られたCSRFトークン発行用のエンドポイントにアクセスし、<code>auth:sanctum</code>ミドルウェアで守られたAPIにCSRFトークンをつけてアクセスすることで認証を行います。</p>
<p data-id="886d041b-45d5-46d8-a7ba-7232e16c180f">一方、stateless guard（トークン認証）は、APIなどでよく使われる認証方式です。クライアントは、APIトークンをリクエストヘッダーに含めてAPIにアクセスします。サーバー側は、そのトークンを検証することで認証を行います。Sanctumでは、<code>sanctum</code>ガードがこのstateless guardに該当します。<code>auth:sanctum</code>ミドルウェアを用いることで、リクエストヘッダーに含まれるAPIトークンを検証し、認証を行います。</p>
<table data-id="951167ec-f581-4420-a2bc-274fa8e565a3">
<colgroup>
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="1d02ecca-2aed-4e20-bd7b-fcd4852c2e0f">ガード</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="45c77a9b-3c27-4027-b997-e34e12534770">説明</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="1d49b9da-b9a0-4c3f-a467-efab6b1e9040"><code>web</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="850e3f7f-584b-4e3c-9c3f-dc14cfff25ff">セッション認証(stateful)</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="247e4732-c23f-4363-af0f-62cc7d85935b"><code>sanctum</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="588a0392-af71-4e24-9a92-d6ced893d322">トークン認証(stateless)</p>
</td>
</tr>
</tbody>
</table>
<p data-id="67325153-6576-429d-8f0f-b561f90bca86">Sanctumでは、<code>web</code>ガードと<code>sanctum</code>ガードを併用することで、WebアプリケーションとAPIの両方でシームレスな認証を実現できます。Basic認証はstatelessな認証方式であるため、Sanctumの<code>sanctum</code>ガードと組み合わせて使用することができます。</p>
<h3 id="19b4b703-21b3-446f-8a73-b9a2091c1127" data-id="19b4b703-21b3-446f-8a73-b9a2091c1127" data-toc-id="19b4b703-21b3-446f-8a73-b9a2091c1127">認証方式によるルーティング設計</h3>
<p data-id="d01168d1-edf2-41d5-93e5-8ea44894a8e1">APIにおいてBasic認証とBearer認証を共存させる場合、ルーティング設計が重要になります。適切にルーティングを設計することで、それぞれの認証方式を必要とするエンドポイントを明確に区別し、セキュリティと利便性を両立させることができます。</p>
<p data-id="3babea4c-d082-4d8d-a20b-b6ab7a6d95c2">たとえば、管理画面へのアクセスにはBasic認証を適用し、外部システムとの連携に用いるAPIにはBearer認証を適用するといった使い分けが可能です。</p>
<table data-id="154dbeaf-5dcc-4d83-8cf6-f3ae30cf0bd1">
<colgroup>
<col />
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="623d5f88-ef10-4cb4-af58-08a64f3350fa">認証方式</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="36b51bb6-5491-4aa3-b6fa-2512a59e9be3">適用エンドポイント</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="077f8aab-0628-4a34-9734-1435a2336cc4">説明</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="6924cd2f-6b93-4cc1-8787-b11bcd8c2831">Basic認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="c186b79b-b3cd-4b9d-b91a-ce4878136052">/admin</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="486605d1-8a9e-4082-b147-12f076eb69c0">管理画面へのアクセス</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="80483df9-e6f8-4175-b910-a245ced430a1">Bearer認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="417a358b-039d-4016-89fb-c196229e1b21">/api/v1/*</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="6ed741d2-d261-4c18-b6dd-5ab042197002">外部システム連携API</p>
</td>
</tr>
</tbody>
</table>
<p data-id="2bf051f2-038e-4f0b-b963-6003820adba5">このようにルーティングを設計することで、管理画面へのアクセスはBasic認証で保護し、APIへのアクセスはBearer認証で保護することができます。<br />
また、Basic認証とBearer認証の両方を適用したいエンドポイントも設計できます。<br />
例えば、開発環境ではBasic認証を適用し、本番環境ではBearer認証を適用するといった切り替えも可能です。</p>
<h2 id="6aab9c79-5a72-440e-81c9-019d40242bf4" data-id="6aab9c79-5a72-440e-81c9-019d40242bf4" data-toc-id="6aab9c79-5a72-440e-81c9-019d40242bf4">ハマりどころと解決策</h2>
<p data-id="5d7a0814-a175-42b0-8cf6-21d193cc026e">Basic認証とBearer認証を共存させる際に発生しやすい問題と、その解決策を紹介します。</p>
<p data-id="49fb2100-2436-4d14-b6ab-43ac30b9e997"><em>Bearer認証特有のハマりどころ</em><br />
Bearer認証は<code>Authorization</code>ヘッダを利用するため、他の認証方式、例えばBasic認証と衝突する可能性があります。<br />
具体的には、Basic認証が必要な環境下でBearer認証を利用する場合、認証が正常に動作しないケースがあります。<br />
これは、<code>Authorization</code>ヘッダの値が両方の認証方式で競合してしまうことが原因です。</p>
<p data-id="2d46c827-658f-4a5f-af8c-d9258fd2f15b"><em>解決策</em></p>
<p data-id="bfc44691-a750-42b9-ad9f-b60fe2836438">この問題を解決するためには、<code>Bearer</code>トークンを送信するヘッダを変更する方法があります。例えば、<code>X-Authorization</code>ヘッダを利用するなど、<code>Authorization</code>ヘッダと異なるヘッダ名を使用することで競合を回避できます。<br />
Laravelでは、<code>$request-&gt;bearerToken()</code>メソッドでBearerトークンを取得しますが、このメソッドをカスタマイズすることで、<code>X-Authorization</code>ヘッダからもトークンを取得できるように変更できます。</p>
<p data-id="f4750bd2-cd63-429f-9e03-0291226af377"><em>カスタマイズ例</em></p>
<pre><code class="language-php">    public function bearerToken()
    {
        $header = $this-&gt;header('X-Authorization', null) ?? $this-&gt;header('Authorization', '');
        if (Str::startsWith($header, 'Bearer ')) {
            return Str::substr($header, 7);
        }
    }
</code></pre>
<p data-id="437006ea-3ad1-4fe2-a524-185e1813508e">上記のように、<code>bearerToken()</code>メソッドをオーバーライドし、<code>X-Authorization</code>ヘッダの値もチェックするように変更することで、<code>Authorization</code>ヘッダとの競合を回避できます。<br />
ただし、このカスタマイズは<code>vendor</code>ディレクトリ内のファイルを直接変更するのではなく、<code>composer.json</code>の<code>files</code>セクションで修正後のファイルを読み込むように設定し、<code>exclude-from-classmap</code>で元ファイルを無効化する必要があります。<br />
これにより、<code>vendor</code>ディレクトリのファイルを直接変更せずにカスタマイズを適用できます。</p>
<h3 id="7a989b8d-fca7-4922-bc92-09d91e40bd3a" data-id="7a989b8d-fca7-4922-bc92-09d91e40bd3a" data-toc-id="7a989b8d-fca7-4922-bc92-09d91e40bd3a">CORSエラーと解決策</h3>
<p data-id="566e17a5-c4df-4987-8930-96bb6e882fd5">CORS（Cross-Origin Resource Sharing）エラーは、異なるオリジン（ドメイン、プロトコル、ポートの組み合わせ）からリソースにアクセスしようとした際に発生するセキュリティエラーです。Sanctumを利用したAPIへのアクセスでこのエラーが発生した場合、ブラウザはAPIからのレスポンスをブロックします。</p>
<table data-id="5a2421f3-6b2a-4e20-870e-5efb630a7c50">
<colgroup>
<col />
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="06723ac7-1660-417a-9a2b-ab4d8c33a67a">エラー</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="b0ee6180-2788-4a5a-8ac3-e2ef2f266101">原因</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="d9620a87-39a2-4722-8336-ada6f480ed10">解決策</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="4e6a5ce9-0d3b-45c9-b110-05a7f107c68e"><code>Access to XMLHttpRequest... has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="ad5c6e55-823d-426e-92b6-ea095e461705">サーバー側でCORSヘッダーが適切に設定されていない</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="1b757390-73b1-4300-a2e2-68b5a75d8d22">Laravelでは<code>fruitcake/laravel-cors</code>パッケージを利用することで、CORSヘッダーを簡単に設定できます。<code>config/cors.php</code>で許可するオリジンを設定します。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="94a0d8c9-9e68-43ba-8d8c-39c4150fad5b"><code>Access to XMLHttpRequest... has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="1f5442b5-2304-4549-a7a9-d33a10f79479"><code>Authorization</code>ヘッダーが許可されていない</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="e3264c22-83a7-49c3-98f0-b537e89c190f"><code>config/cors.php</code>の<code>allowed_headers</code>に<code>Authorization</code>を追加します。<code>allowed_headers</code>を<code>['*']</code>に設定することで、全てヘッダーを許可することも可能です。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="65a53937-f101-4309-8efa-ce27a7ccc16a"><code>Access to XMLHttpRequest... has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.</code></p>
</td>
<td colspan="1" rowspan="1">
<p data-id="85b833c7-0b01-4338-a47d-97424ce955d5">credentialsが許可されていない</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="92b949b8-6f9b-451f-b20a-42e151aac987"><code>config/cors.php</code>の<code>supports_credentials</code>を<code>true</code>に設定します。</p>
</td>
</tr>
</tbody>
</table>
<p data-id="c76d311e-4c65-4f12-9a15-d908d4695343">これらの設定後、サーバーを再起動してください。</p>
<h3 id="b92e96aa-d8cb-4161-ba59-50488c277ab5" data-id="b92e96aa-d8cb-4161-ba59-50488c277ab5" data-toc-id="b92e96aa-d8cb-4161-ba59-50488c277ab5">401エラー、419エラーへの対処</h3>
<p data-id="65696f11-da2a-43b2-b3ae-403537da52ef">API認証でよく遭遇する401 Unauthorizedエラーと419 Page Expiredエラーについて、その原因と解決策を解説します。</p>
<table data-id="4f8d229f-d5f7-43e9-afe5-f454c1417add">
<colgroup>
<col />
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="d0c54a97-6510-4894-9b57-d83ad333c025">エラーコード</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="fa102c6d-fe44-4aaa-a7c5-94b1606a543b">原因</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="6ec63bc8-e840-4c2d-8dd9-cdc2032a428b">解決策</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="eb837c7c-ff5f-46a3-a687-2e95ee60c338">401 Unauthorized</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="d5c7e5fa-93b7-4be0-b38c-46471a780a35">認証情報が正しくない、または存在しない</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="5981ba5d-4d67-40ca-b748-e477727659d1">APIトークンが正しく設定されているか確認する。トークンの期限切れにも注意が必要です。</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="428403ad-8dad-495a-9b3d-bdb11ef39a83">419 Page Expired</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="46a6bf25-2e61-4704-ab41-95060031241d">CSRFトークンの不一致、またはセッションの期限切れ</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="31fdee1b-68bb-4b65-a8f7-51446097639c">Sanctumを利用している場合は、<code>SANCTUM_STATEFUL_DOMAINS</code>の設定を確認し、ブラウザからのリクエストの場合はCSRFトークンをヘッダーに含めるようにしましょう。</p>
</td>
</tr>
</tbody>
</table>
<p data-id="81d70e24-f0e5-40e6-b584-e8f3336062b4">記載されている通り、.envファイルの設定ミスでAPIが401エラーを返すケースがあります。<code>SANCTUM_STATEFUL_DOMAINS</code> には <code>www.</code> を含めたドメインを正しく設定する必要があります。設定後、設定内容が反映されているか確認しましょう。また、セッションの期限切れも419エラーの原因となります。セッションの有効期限を適切に設定することで、この問題を回避できます。</p>
<h3 id="01e31cb5-dd8e-4772-87d4-c8326af09f0d" data-id="01e31cb5-dd8e-4772-87d4-c8326af09f0d" data-toc-id="01e31cb5-dd8e-4772-87d4-c8326af09f0d">トークンのリフレッシュ方法</h3>
<p data-id="26a34d0c-74dd-435b-942b-e34a148c0e77">Sanctumにおけるトークンのリフレッシュ方法は、SPA認証とAPIトークン認証で異なります。SPA認証では、Sanctumが自動的にトークンのリフレッシュを処理します。ユーザーがログインしている間、Sanctumはバックグラウンドで新しいトークンを発行し、古いトークンを無効化します。そのため、開発者はトークンのリフレッシュ処理を明示的に実装する必要はありません。</p>
<p data-id="4425d775-f73c-41d9-963f-ee7a0132aa5b">一方、APIトークン認証では、トークンのリフレッシュは手動で行う必要があります。APIトークンには有効期限が設定されており、期限が切れたトークンは無効になります。期限切れのトークンでAPIリクエストを送信すると、401エラーが返されます。</p>
<p data-id="edddeac3-6d74-474a-ba94-4c7f6ae000b5">APIトークンをリフレッシュするには、<code>/sanctum/csrf-cookie</code>ルートにPOSTリクエストを送信し、CSRFトークンを取得します。次に、取得したCSRFトークンをヘッダーに設定し、認証情報とともに<code>/login</code>ルートにPOSTリクエストを送信します。認証が成功すると、新しいAPIトークンが発行されます。</p>
<table data-id="af1efcff-5913-47b6-89bf-228d77ce0a4a">
<colgroup>
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="0b8b22d4-ea95-4096-81fa-cd518ab46e07">認証方式</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="6692ff0f-12bc-4af0-a5b7-b5ca4d8b606c">リフレッシュ方法</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="73b346d0-3843-4b98-acca-419ee840e48d">SPA認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="93663bc0-1817-4755-9119-9eefb77e2add">自動リフレッシュ</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="b3996463-415e-4e69-941e-93e97759cb26">APIトークン認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="9f05cee2-8bf7-402a-b451-d40f4470f59c">手動リフレッシュ</p>
</td>
</tr>
</tbody>
</table>
<p data-id="62707df7-20ec-4c9b-9c72-09f490e757b4">トークンのリフレッシュ処理を適切に実装することで、APIのセキュリティを維持し、ユーザーの利便性を向上させることができます。</p>
<h3 id="6ea0bdfb-d3b6-45ef-b91a-caab76c10628" data-id="6ea0bdfb-d3b6-45ef-b91a-caab76c10628" data-toc-id="6ea0bdfb-d3b6-45ef-b91a-caab76c10628">Basic認証とBearer認証の共存設定時の注意点</h3>
<p data-id="dbbcf113-953d-4577-8b99-6631b975de67">Basic認証とBearer認証を共存させる場合、Authorizationヘッダの利用について注意が必要です。両方の認証方式でこのヘッダを利用するため、競合が発生する可能性があります。</p>
<table data-id="a4ef6f81-c9b6-49d7-9d03-eca7610b1ca0">
<colgroup>
<col />
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="0a9fee7b-5ca2-457f-a597-506e26755560">認証方式</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="937a602f-22d1-4ce0-b83d-ff9189f90dd7">ヘッダ</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="666f4c2a-7f2d-4228-93ef-7238b9765f90">内容</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="02f637f4-9244-4888-8819-ae9f3489195f">Basic認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="272dacbc-5fbd-4f6d-b734-5dbf7de0b138">Authorization</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="ac20a19b-54e8-4035-b782-013f0aac4b34"><code>Basic {credentials}</code></p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="76cc950b-835f-4b23-b269-461403dcdeed">Bearer認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="e3e9489a-fe62-4654-940f-0baa28563b46">Authorization</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="e42a7330-79a3-443f-8187-b43b4942f26c"><code>Bearer {token}</code></p>
</td>
</tr>
</tbody>
</table>
<p data-id="428737d3-58f0-4daf-b12c-f438171ed214">上記のように、Basic認証では<code>Basic</code>に続いて認証情報が、Bearer認証では<code>Bearer</code>に続いてトークンがAuthorizationヘッダに含まれます。</p>
<p data-id="fbfb7f7e-e82d-494f-bad0-9a608e0fa177">既存システムでBearer認証をAuthorizationヘッダで利用している場合、ヘッダ名を変更せずに共存させるには、サーバー側で条件分岐を行うなどの対応が必要になります。例えば、特定の環境のみ別のヘッダ(例：X-Authorization)でBearerトークンを受け付けるように変更できます。</p>
<p data-id="5da257b9-b0a7-46ad-97b2-3a9d785a12c0">Laravelでは、<code>$request-&gt;bearerToken()</code>でBearerトークンを取得しますが、この部分をカスタマイズし、<code>Authorization</code>ヘッダに加え、<code>X-Authorization</code>ヘッダからもトークンを取得できるように変更することで対応可能です。</p>
<h2 id="c5c089f1-d441-4b4b-a423-9f0729b6ceaa" data-id="c5c089f1-d441-4b4b-a423-9f0729b6ceaa" data-toc-id="c5c089f1-d441-4b4b-a423-9f0729b6ceaa">まとめ</h2>
<p data-id="fc6f0646-ebac-4d34-b5aa-c9c6d98c3e39">この記事では、Laravel Sanctumを用いてBasic認証とBearer認証を共存させる方法と、その際に発生しやすい問題点と解決策について解説しました。SanctumはシンプルなAPI認証を提供する一方で、複数の認証方式を柔軟に組み合わせることができるため、様々なシステム構成に対応できます。</p>
<p data-id="6c8e303e-1eea-45c9-9292-90f158065899">SPAとAPIサーバー間の通信にはBearer認証を、特定の管理画面などにはBasic認証を適用することで、セキュリティレベルを調整しながら開発効率を高めることが可能です。</p>
<p data-id="839b806a-2753-4982-8946-9156aaa3be74">共存設定の要は、ミドルウェア<code>auth:sanctum</code>の適用範囲を適切に制御することです。ルーティング設定を活用して、それぞれの認証方式を適用するエンドポイントを明確に区別することで、認証に関する予期せぬ動作を防ぎ、安全なシステムを構築できます。</p>
<table data-id="65b811cd-f462-4bee-9f06-efc62e3429f8">
<colgroup>
<col />
<col />
<col /></colgroup>
<tbody>
<tr>
<th colspan="1" rowspan="1">
<p data-id="d5bb9df7-7924-4dd7-91e5-a9bbf8ed1ff0">認証方式</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="158ddcdb-db3a-4cd7-ab75-8ae396be64aa">適用例</p>
</th>
<th colspan="1" rowspan="1">
<p data-id="880cd323-5d49-4d58-9960-0d635c9d4cde">メリット</p>
</th>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="67c03c87-dd32-414e-92c7-4346757f36f8">Basic認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="c0c94e1b-7aff-4f00-9ab5-39eafc0f7b22">管理画面、開発環境</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="d62c34c3-40df-4696-800a-7349e06ace94">簡便な実装</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p data-id="1f3d2889-b793-40eb-8f9d-60b609df65a3">Bearer認証</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="1922628d-741d-48b6-9422-6b0e2cc3f0ca">SPA、モバイルアプリ</p>
</td>
<td colspan="1" rowspan="1">
<p data-id="102f64de-fb18-47b5-9a20-d15535f37b94">セキュリティレベルの高いAPIアクセス</p>
</td>
</tr>
</tbody>
</table>
<p data-id="f36e3815-07cf-42a5-a9d0-15358cb5b58f">CORSエラーや401エラー、419エラーといったよくある問題は、設定ミスやリクエストヘッダーの不備が原因であることが多いです。エラーメッセージを注意深く確認し、適切な設定を行うことで解決できます。</p>
<p data-id="8a20efcb-1564-4d1b-8f86-61864d4cfd13">Sanctumの柔軟性を活かして、安全かつ効率的なAPI認証を実現しましょう。</p>
<p><script type="text/javascript">
    document.addEventListener('DOMContentLoaded', function () {
        var contentsList = document.getElementById('toc'); // 目次を追加する先(table of contents)
        var div = document.createElement('div'); // 作成する目次のコンテナ要素</p>
<p>        // .node-content配下のh2、h3要素を全て取得する
        var matches = document.querySelectorAll('.node-content h2, .node-content h3');</p>
<p>        // 取得した見出しタグ要素の数だけ以下の操作を繰り返す
        matches.forEach(function (value, i) {
            // 見出しタグ要素のidを取得し空の場合は内容をidにする
            var id = value.id;
            if(id === '') {
                id = value.textContent;
                value.id = id;
            }</p>
<p>            // 要素がh2タグの場合
            if(value.tagName === 'H2') {
                var ul = document.createElement('ul');
                var li = document.createElement('li');
                var a = document.createElement('a');</p>
<p>                // 追加する</p>
<ul>
<li><a>タイトル</a></li>
</ul>
<p>を準備する
                a.innerHTML = value.textContent;
                a.href = '#' + value.id;
                li.appendChild(a)
                ul.appendChild(li);</p>
<p>                // コンテナ要素である</p>
<div>の中に要素を追加する
                div.appendChild(ul);
            }</p>
<p>            // 要素がh3タグの場合
            if(value.tagName === 'H3') {
                var ul = document.createElement('ul');
                var li = document.createElement('li');
                var a = document.createElement('a');</p>
<p>                // コンテナ要素である</p>
<div>の中から最後の</p>
<li>を取得する。
                var lastUl = div.lastElementChild;
                var lastLi = lastUl.lastElementChild;</p>
<p>                // 追加する</p>
<ul>
<li><a>タイトル</a></li>
</ul>
<p>を準備する
                a.innerHTML = value.textContent;
                a.href = '#' + value.id;
                li.appendChild(a)
                ul.appendChild(li);</p>
<p>                // 最後の</p>
<li>の中に要素を追加する
                lastLi.appendChild(ul);
            }
        });</p>
<p>        // 最後に画面にレンダリング
        contentsList.appendChild(div);
    });
</script></p><p>The post <a href="https://www.ye-p.co.jp/blog/368-2">Laravel SanctumでBasic認証とBearer認証を共存させる方法とハマりどころ</a> first appeared on <a href="https://www.ye-p.co.jp">株式会社yep</a>.</p>]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
