イントロダクションIntroduction
Laravel Sanctum(サンクタム:聖所)はSPA(Single Page Applications)やモバイルアプリケーションのための、シンプルでトークンベースのAPIを使った羽のように軽い認証システムです。Sanctumはアプリケーションのユーザーのアカウントごとに、複数のAPIトークンを生成できます。これらのトークンには、実行可能なアクションを限定する能力(アビリティ)/スコープを与えられます。Laravel Sanctum provides a featherweight authentication system for SPAs (single page applications), mobile applications, and simple, token based APIs. Sanctum allows each user of your application to generate multiple API tokens for their account. These tokens may be granted abilities / scopes which specify which actions the tokens are allowed to perform.
動作の仕組みHow It Works
Laravel Sanctumは、2つの別個の問題を解決するために存在します。Laravel Sanctum exists to solve two separate problems.
APIトークンAPI Tokens
1つ目はOAuthの煩雑さなしにユーザーへAPIトークンを発行するためのシンプルなパッケージの提供です。たとえば、ユーザーがAPIトークンを自分のアカウントへ生成すると想像してください。アプリケーションへ「アカウント設定」ページを用意するでしょう。こうしたトークンを生成し、管理するためにSanctumが使われます。こうしたトークンへは通常数年にも渡る、とても長い有効期間を指定します。しかし、ユーザー自身はいつでも破棄可能です。First, it is a simple package to issue API tokens to your users without the complication of OAuth. This feature is inspired by GitHub "access tokens". For example, imagine the "account settings" of your application has a screen where a user may generate an API token for their account. You may use Sanctum to generate and manage those tokens. These tokens typically have a very long expiration time (years), but may be manually revoked by the user at anytime.
この機能を実現するため、Laravel Sanctumは一つのデータベーステーブルへユーザーのAPIトークンを保存しておき、受信したリクエストがAuthorization
ヘッダに有効なAPIトークンを含んでいるかにより認証します。Laravel Sanctum offers this feature by storing user API tokens in a single database table and authenticating incoming requests via the Authorization
header which should contain a valid API token.
SPA認証SPA Authentication
2つ目の存在理由は、Laravelが提供するAPIを使用し通信する必要があるシングルページアプリケーション(SPA)へ、シンプルな認証方法を提供するためです。こうしたSPAはLaravelアプリケーションと同じリポジトリにあっても、まったく別のリポジトリに存在していてもかまいません。たとえばSPAがVue CLIを使用して生成された場合などです。Second, Sanctum exists to offer a simple way to authenticate single page applications (SPAs) that need to communicate with a Laravel powered API. These SPAs might exist in the same repository as your Laravel application or might be an entirely separate repository, such as a SPA created using Vue CLI.
Sanctumはこの機能の実現のためにトークンは一切使用しません。代わりにLaravelへ組み込まれているクッキーベースのセッション認証サービスを使用します。これにより、XSSによる認証情報リークに対する保護と同時に、CSRF保護・セッションの認証を提供しています。皆さんのSPAのフロントエンドから送信されるリクエストに対し、Sanctumはクッキーだけを使用して認証を確立しようとします。For this feature, Sanctum does not use tokens of any kind. Instead, Sanctum uses Laravel's built-in cookie based session authentication services. This provides the benefits of CSRF protection, session authentication, as well as protects against leakage of the authentication credentials via XSS. Sanctum will only attempt to authenticate using cookies when the incoming request originates from your own SPA frontend.
{tip} It is perfectly fine to use Sanctum only for API token authentication or only for SPA authentication. Just because you use Sanctum does not mean you are required to use both features it offers.
">Tip!! APIトークン認証だけを使う場合、もしくはSPA認証だけを使う場合のどちらにもSanctumは適しています。Sanctumが2つの機能を提供しているからといって、両方共に使う必要はありません。
インストールInstallation
Laravel SanctumはComposerでインストールします。You may install Laravel Sanctum via Composer:
composer require laravel/sanctum
次に、vendor:publish
Artisanコマンドを使用して、Sanctumの設定とマイグレーションをリソース公開します。sanctum
設定ファイルがconfig
ディレクトリに設置されます。Next, you should publish the Sanctum configuration and migration files using the vendor:publish
Artisan command. The sanctum
configuration file will be placed in your config
directory:
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
最後に、データベースマイグレーションを実行してください。SanctumはAPIトークンを保存しておくデータベースを1つ作成します。Finally, you should run your database migrations. Sanctum will create one database table in which to store API tokens:
php artisan migrate
SPAの認証のためにSanctumを活用しようと計画している場合は、app/Http/Kernel.php
ファイル中のapi
ミドルウェアグループへ、Sanctumのミドルウェアを追加します。Next, if you plan to utilize Sanctum to authenticate an SPA, you should add Sanctum's middleware to your api
middleware group within your app/Http/Kernel.php
file:
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
'api' => [
EnsureFrontendRequestsAreStateful::class,
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
マイグレーションのカスタマイズMigration Customization
Sanctumのデフォルトマイグレーションを使用しない場合は、AppServiceProvider
のregister
メソッドの中で、Sanctum::ignoreMigrations
を必ず呼び出してください。デフォルトマイグレーションは、php artisan vendor:publish --tag=sanctum-migrations
を使えばエクスポートできます。If you are not going to use Sanctum's default migrations, you should call the Sanctum::ignoreMigrations
method in the register
method of your AppServiceProvider
. You may export the default migrations using php artisan vendor:publish --tag=sanctum-migrations
.
APIトークン認証API Token Authentication
SPA認証を使用してください。{tip} You should not use API tokens to authenticate your own first-party SPA. Instead, use Sanctum's built-in SPA authentication[#spa-authentication].
">Tip!! 皆さん自身のファーストパーティSPAを認証するためにAPIトークンを決して利用してはいけません。代わりに、Sanctumの組み込み
APIトークン発行Issuing API Tokens
APIリクエスト認証に使用するため、APIトークン/パーソナルアクセストークンをSanctumは発行します。APIトークンを利用するリクエストを作成する場合は、Bearer
トークンとしてAuthorization
ヘッダにトークンを含める必要があります。Sanctum allows you to issue API tokens / personal access tokens that may be used to authenticate API requests. When making requests using API tokens, the token should be included in the Authorization
header as a Bearer
token.
ユーザーにトークンを発行開始するには、UserモデルでHasApiTokens
トレイトを使用してください。To begin issuing tokens for users, your User model should use the HasApiTokens
trait:
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
}
トークンを発行するには、createToken
メソッドを使用します。このcreateToken
メソッドはLaravel\Sanctum\NewAccessToken
インスタンスを返します。APIトークンはデータベースへ格納される前に、SHA-256を使いハッシュされますが、NewAccessToken
インスタンスのplainTextToken
プロパティにより、平文の値へアクセスできます。トークンを生成したら、ユーザーへこの値をすぐに表示しなくてはなりません。To issue a token, you may use the createToken
method. The createToken
method returns a Laravel\Sanctum\NewAccessToken
instance. API tokens are hashed using SHA-256 hashing before being stored in your database, but you may access the plain-text value of the token using the plainTextToken
property of the NewAccessToken
instance. You should display this value to the user immediately after the token has been created:
$token = $user->createToken('token-name');
return $token->plainTextToken;
そのユーザーのトークンすべてにアクセスするには、HasApiTokens
トレイトが提供するtokens
Eloquentリレーションを使用します。You may access all of the user's tokens using the tokens
Eloquent relationship provided by the HasApiTokens
trait:
foreach ($user->tokens as $token) {
//
}
トークンのアビリティToken Abilities
OAuthの「スコープ」と同じように、Sanctumは「アビリティ(能力)」をトークンへ割り付けられます。createToken
メソッドの第2引数として、アビリティの文字列の配列を渡してください。Sanctum allows you to assign "abilities" to tokens, similar to OAuth "scopes". You may pass an array of string abilities as the second argument to the createToken
method:
return $user->createToken('token-name', ['server:update'])->plainTextToken;
Sanctumにより認証されたリクエストを処理するとき、そのトークンが特定のアビリティを持っているかをtokenCan
メソッドで判定できます。When handling an incoming request authenticated by Sanctum, you may determine if the token has a given ability using the tokenCan
method:
if ($user->tokenCan('server:update')) {
//
}
">Tip!! 利便性のため、
tokenCan
メソッドは受信認証済みリクエストがファーストパーティSPAから送信されたとき、もしくはSanctumの組み込みSPA認証を使用している場合は常にtrue
を返します。{tip} For convenience, thetokenCan
method will always returntrue
if the incoming authenticated request was from your first-party SPA and you are using Sanctum's built-in SPA authentication[#spa-authentication].
ルート保護Protecting Routes
受信リクエストをすべて認証済みに限定し、ルートを保護する場合は、routes/api.php
ファイル中のAPIルートに対してsanctum
認証ガードを指定する必要があります。このガードは受信リクエストが認証済みであると保証します。そのリクエストが皆さん自身のSPAからのステートフルな認証済みであるか、もしくはサードパーティからのリクエストの場合は有効なAPIトークンのヘッダを持っているかのどちらか一方であるか確認します。To protect routes so that all incoming requests must be authenticated, you should attach the sanctum
authentication guard to your API routes within your routes/api.php
file. This guard will ensure that incoming requests are authenticated as either a stateful authenticated requests from your SPA or contain a valid API token header if the request is from a third party:
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
トークン破棄Revoking Tokens
データベースから削除し、トークンを「破棄」するには、HasApiTokens
トレイトが提供しているtokens
リレーションを使用します。You may "revoke" tokens by deleting them from your database using the tokens
relationship that is provided by the HasApiTokens
trait:
// 全トークンの破棄
$user->tokens()->delete();
// このユーザーの現在のトークンを取り消す
$request->user()->currentAccessToken()->delete();
// 特定トークンの破棄
$user->tokens()->where('id', $id)->delete();
SPA認証SPA Authentication
Laravelを使ったAPIと通信する必要があるシングルページアプリケーション(SPA)へ、シンプルな認証方法を提供するためにSanctumを開発しました。こうしたSPAはLaravelアプリケーションと同じリポジトリにあっても、もしくはVue CLIを使用して生成したSPAのように、まったく別のリポジトリに存在していてもかまいません。Sanctum exists to offer a simple way to authenticate single page applications (SPAs) that need to communicate with a Laravel powered API. These SPAs might exist in the same repository as your Laravel application or might be an entirely separate repository, such as a SPA created using Vue CLI.
Sanctumはこの機能の実現のためにトークンは一切使用しません。Laravelへ組み込まれているクッキーベースのセッション認証サービスを使用します。これにより、XSSによる認証情報リークに対する保護と同時に、CSRF保護・セッションの認証を提供しています。皆さんのSPAのフロントエンドから送信されるリクエストに対し、Sanctumはクッキーだけを使用して認証を確立しようとします。For this feature, Sanctum does not use tokens of any kind. Instead, Sanctum uses Laravel's built-in cookie based session authentication services. This provides the benefits of CSRF protection, session authentication, as well as protects against leakage of the authentication credentials via XSS. Sanctum will only attempt to authenticate using cookies when the incoming request originates from your own SPA frontend.
Note: {note} In order to authenticate, your SPA and API must share the same top-level domain. However, they may be placed on different subdomains.
認証するために、SPAとAPIは同じトップレベルドメインである必要があります。しかしながら、別のサブドメインに設置することは可能です。
設定Configuration
ファーストパーティドメインの設定Configuring Your First-Party Domains
最初に、どのドメインから皆さんのSPAがリクエストを作成するのか設定する必要があります。sanctum
設定ファイルのstateful
設定オプションを利用してこのドメインを指定します。この設定を元にして皆さんのAPIへリクエストを作成するときに、Laravelのセッションクッキーを使用することで「ステートフル」な認証を維持する必要があるドメインを判断します。First, you should configure which domains your SPA will be making requests from. You may configure these domains using the stateful
configuration option in your sanctum
configuration file. This configuration setting determines which domains will maintain "stateful" authentication using Laravel session cookies when making requests to your API.
Note:
ポート(127.0.0.1:8000
)を含むURLによりアプリケーションにアクセスする場合は、ドメインにポート番号を含める必要があります。{note} If you are accessing your application via a URL that includes the port (127.0.0.1:8000
), you should ensure that you include the port number with the domain.
SanctumミドルウェアSanctum Middleware
次に、app/Http/Kernel.php
ファイル中のapi
ミドルウェアグループへ、Sanctumのミドルウェアを追加する必要があります。このミドルウェアは皆さんのSPAから受信するリクエストが、Laravelのセッションクッキーを使用して確実に認証できるようにする責任を負っています。同時に、サードパーティやモバイルアプリからのリクエストに対し、APIトークンを使用した認証ができるようにしています。Next, you should add Sanctum's middleware to your api
middleware group within your app/Http/Kernel.php
file. This middleware is responsible for ensuring that incoming requests from your SPA can authenticate using Laravel's session cookies, while still allowing requests from third parties or mobile applications to authenticate using API tokens:
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
'api' => [
EnsureFrontendRequestsAreStateful::class,
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
CORSとクッキーCORS & Cookies
別のサブドメイン上のSPAからの認証でアプリケーションにトラブルが起きているのであれば、CORS(Cross-Origin Resource Sharing)かセッションクッキーの設定を間違えたのでしょう。If you are having trouble authenticating with your application from an SPA that executes on a separate subdomain, you have likely misconfigured your CORS (Cross-Origin Resource Sharing) or session cookie settings.
アプリケーションのCORS設定で、Access-Control-Allow-Credentials
ヘッダにTrue
の値を返すため、アプリケーションのcors
設定ファイル中のsupports_credentials
オプションをtrue
にしてください。You should ensure that your application's CORS configuration is returning the Access-Control-Allow-Credentials
header with a value of True
by setting the supports_credentials
option within your application's cors
configuration file to true
.
さらに、グローバルaxios
インスタンス上で、withCredentials
オプションを有効にしているかも確認してください。通常、これはresources/js/bootstrap.js
ファイルで実行されるべきです。In addition, you should enable the withCredentials
option on your global axios
instance. Typically, this should be performed in your resources/js/bootstrap.js
file:
axios.defaults.withCredentials = true;
最後に、アプリケーションのセッションクッキードメイン設定で、ルートドメイン下の全サブドメインをサポートしているかを確認する必要があります。session
設定ファイル中で、.
にドメイン名を続ければ指定できます。Finally, you should ensure your application's session cookie domain configuration supports any subdomain of your root domain. You may do this by prefixing the domain with a leading .
within your session
configuration file:
'domain' => '.domain.com',
認証Authenticating
皆さんのSPAを認証するには、SPAのログインページで最初に/sanctum/csrf-cookie
ルートへのリクエストを作成し、アプリケーションのCSRF保護を初期化しなくてはなりません。To authenticate your SPA, your SPA's login page should first make a request to the /sanctum/csrf-cookie
route to initialize CSRF protection for the application:
axios.get('/sanctum/csrf-cookie').then(response => {
// ログイン処理…
});
このリクエスト中にLaravelは現在のCSRFトークンを持つXSRF-TOKEN
クッキーをセットします。このトークンは続くリクエストでX-XSRF-TOKEN
ヘッダに渡さなければなりません。AxiosとAngular HttpClientは自動的にこれを処理します。During this request Laravel will set an XSRF-TOKEN
cookie containing the current CSRF token. This token should then be passed in an X-XSRF-TOKEN
header on subsequent requests, which libraries like Axios and the Angular HttpClient will do automatically for you.
CSRF保護の初期化後、通常Laravelでは/login
であるルートへPOST
リクエストを送る必要があります。このlogin
ルートは、laravel/ui
認証スカフォールドが提供しています。Once CSRF protection has been initialized, you should make a POST
request to the typical Laravel /login
route. This /login
route may be provided by the laravel/ui
authentication scaffolding[/docs/{{version}}/authentication#introduction] package.
ログインリクエストに成功するとユーザーは認証され、Laravelのバックエンドがクライアントへ発行しているセッションクッキーにより、APIルートに対する以降のリクエストも自動的に認証されます。If the login request is successful, you will be authenticated and subsequent requests to your API routes will automatically be authenticated via the session cookie that the Laravel backend issued to your client.
">Tip!!
/login
エンドポイントは自由に書けます。ただし標準的な、Laravelが提供する認証サービスベースのセッションをユーザー認証で確実に使用してください。{tip} You are free to write your own/login
endpoint; however, you should ensure that it authenticates the user using the standard, session based authentication services that Laravel provides[/docs/{{version}}/authentication#authenticating-users].
ルート保護Protecting Routes
受信リクエストをすべて認証済みに限定し、ルートを保護する場合は、routes/api.php
ファイル中のAPIルートに対してsanctum
認証ガードを指定する必要があります。このガードは受信リクエストが認証済みであると保証します。そのリクエストが皆さん自身のSPAからのステートフルな認証済みであるか、もしくはサードパーティからのリクエストの場合は有効なAPIトークンのヘッダを持っているかのどちらか一方であるか確認します。To protect routes so that all incoming requests must be authenticated, you should attach the sanctum
authentication guard to your API routes within your routes/api.php
file. This guard will ensure that incoming requests are authenticated as either a stateful authenticated requests from your SPA or contain a valid API token header if the request is from a third party:
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
プライベートブロードキャストチャンネルの認証Authorizing Private Broadcast Channels
SPAでプライベート/プレゼンスブロードキャストチャンネルを使った認証が必要な場合は、routes/api.php
ファイルの中でBroadcast::routes
メソッドを呼び出す必要があります。If your SPA needs to authenticate with private / presence broadcast channels[/docs/{{version}}/broadcasting#authorizing-channels], you should place the Broadcast::routes
method call within your routes/api.php
file:
Broadcast::routes(['middleware' => ['auth:sanctum']]);
次に、Pusherの認証リクエストを成功させるため、Laravel Echoの初期化時に、カスタムPusher authorizer
を用意する必要があります。これにより、アプリケーションが確実にクロスドメインのリクエストを処理できるように設定したaxios
インスタンスをPusherが使用するように設定できます。Next, in order for Pusher's authorization requests to succeed, you will need to provide a custom Pusher authorizer
when initializing Laravel Echo[/docs/{{version}}/broadcasting#installing-laravel-echo]. This allows your application to configure Pusher to use the axios
instance that is properly configured for cross-domain requests[#cors-and-cookies]:
window.Echo = new Echo({
broadcaster: "pusher",
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
encrypted: true,
key: process.env.MIX_PUSHER_APP_KEY,
authorizer: (channel, options) => {
return {
authorize: (socketId, callback) => {
axios.post('/api/broadcasting/auth', {
socket_id: socketId,
channel_name: channel.name
})
.then(response => {
callback(false, response.data);
})
.catch(error => {
callback(true, error);
});
}
};
},
})
モバイルアプリの認証Mobile Application Authentication
あなた自身のAPIに対するモバイルアプリのリクエストを認証するために、Sanctumトークンを使用できます。モバイルアプリのリクエストに対する認証手順は、サードパーティAPIリクエストに対する認証と似ています。しかし、APIトークンの発行方法に多少の違いがあります。You may use Sanctum tokens to authenticate your mobile application's requests to your API. The process for authenticating mobile application requests is similar to authenticating third-party API requests; however, there are small differences in how you will issue the API tokens.
APIトークン発行Issuing API Tokens
まずはじめに、ユーザーのメールアドレス/ユーザー名、パスワード、デバイス名を受け取るルートを作成し、次にこうした認証情報を元に新しいSanctumトークンを受け取ります。このエンドポイントは平文のSanctumトークンを返し、それはモバイルデバイス上に保存され、それ以降のAPIリクエストを作成するために利用されます。To get started, create a route that accepts the user's email / username, password, and device name, then exchanges those credentials for a new Sanctum token. The endpoint will return the plain-text Sanctum token which may then be stored on the mobile device and used to make additional API requests:
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
Route::post('/sanctum/token', function (Request $request) {
$request->validate([
'email' => 'required|email',
'password' => 'required',
'device_name' => 'required',
]);
$user = User::where('email', $request->email)->first();
if (! $user || ! Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
]);
}
return $user->createToken($request->device_name)->plainTextToken;
});
モバイルデバイスが、アプリケーションへのAPIリクエストを作成するためにトークンを使用するときは、Bearer
トークンとしてAuthorization
ヘッダへ渡します。When the mobile device uses the token to make an API request to your application, it should pass the token in the Authorization
header as a Bearer
token.
トークンのアビリティを指定できます。{tip} When issuing tokens for a mobile application, you are also free to specify token abilities[#token-abilities]
">Tip!! モバイルアプリケーションに対してトークンを発行するときにも、自由に
ルート保護Protecting Routes
以前に説明した通り、ルートへsanctum
認証ガードを指定することで、受信リクエストをすべて認証済み必須にし、ルートを保護できます。通常、routes/api.php
ファイルでこのガードを指定したルートを定義します。As previously documented, you may protect routes so that all incoming requests must be authenticated by attaching the sanctum
authentication guard to the routes. Typically, you will attach this guard to the routes defined within your routes/api.php
file:
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
トークン破棄Revoking Tokens
モバイルデバイスに対して発行されたAPIトークンをユーザーが破棄できるようにするため、WebアプリケーションのUIで「アカウント設定」のようなページに一覧表示し、「破棄」ボタンを用意する必要があります。ユーザーが「破棄」ボタンをクリックしたら、データベースからトークンを削除します。HasApiTokens
トレイトが提供するtokens
リレーションにより、そのユーザーのAPIトークンへアクセスできるのを覚えておきましょう。To allow users to revoke API tokens issued to mobile devices, you may list them by name, along with a "Revoke" button, within an "account settings" portion of your web application's UI. When the user clicks the "Revoke" button, you can delete the token from the database. Remember, you can access a user's API tokens via the tokens
relationship provided by the HasApiTokens
trait:
// 全トークンの破棄
$user->tokens()->delete();
// 特定トークンの破棄
$user->tokens()->where('id', $id)->delete();
テストTesting
テストをする時は、Sanctum::actingAs
メソッドでユーザーを認証し、トークンにアビリティを許可する指定を行えます。While testing, the Sanctum::actingAs
method may be used to authenticate a user and specify which abilities are granted to their token:
use App\User;
use Laravel\Sanctum\Sanctum;
public function test_task_list_can_be_retrieved()
{
Sanctum::actingAs(
factory(User::class)->create(),
['view-tasks']
);
$response = $this->get('/api/task');
$response->assertOk();
}
トークンに全アビリティを許可したい場合は、actingAs
メソッドへ*
を含めたアビリティリストを指定します。If you would like to grant all abilities to the token, you should include *
in the ability list provided to the actingAs
method:
Sanctum::actingAs(
factory(User::class)->create(),
['*']
);