Readouble

Laravel 7.x Laravel Airlock

イントロダクションIntroduction

Laravel Airlock(エアーロック)はSPA(Single Page Applications)のための、シンプルでトークンベースのAPIを使った羽のように軽い認証システムです。Airlockはアプリケーションのユーザーのアカウントごとに、複数のAPIトークンを生成できます。これらのトークンには、実行可能なアクションを限定するアビリティ・スコープを与えられます。Laravel Airlock provides a featherweight authentication system for SPAs (single page applications), mobile applications, and simple, token based APIs. Airlock 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

APIトークンAPI Tokens

Laravel Airlockは、別々の問題2つを解決するために存在しています。1つ目はOAuthの煩雑さなしにユーザーへAPIトークンを発行するためのシンプルなパッケージの提供です。たとえば、ユーザーがAPIトークンを自分のアカウントへ生成すると想像してください。アプリケーションへ「アカウント設定」ページを用意するでしょう。こうしたトークンを生成し、管理するためにAirlockが使われます。こうしたトークンへは通常数年にも渡る、とても長い有効期間を指定します。しかし、ユーザー自身はいつでも破棄可能です。Laravel Airlock exists to solve two separate problems. 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 Airlock 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は一つのデータベーステーブルへユーザーのAPIトークンを保存しておき、受信したリクエストがAuthorizationヘッダに有効なAPIトークンを含んでいるかにより認証します。Laravel Airlock 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

lightbulb">Tip!! APIトークン認証だけを使う場合、もしくはAPIトークン認証だけを使う場合のどちらにもAirlockは適しています。Airlockが2つの機能を提供しているからと言っても、両方共に使う必要はありません。{tip} It is perfectly fine to use Airlock only for API token authentication or only for SPA authentication. Just because you use Airlock does not mean you are required to use both features it offers.

2つ目の存在理由は、Laravelが提供するAPIを使用し通信する必要があるシングルページアプリケーション(SPA)へ、シンプルな認証方法を提供するためです。こうしたSPAはLaravelアプリケーションと同じリポジトリにあっても、まったく別のリポジトリに存在していてもかまいません。Second, Airlock 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.

Airlockはこの機能の実現のためにトークンは一切使用しません。Laravelへ組み込まれているクッキーベースのセッション認証サービスを使用します。これにより、XSSによる認証情報リークに対する保護と同時に、CSRF保護・セッションの認証を提供しています。皆さんのSPAのフロントエンドから送信されるリクエストに対し、Airlockはクッキーだけを使用して認証を確立しようとします。For this feature, Airlock does not use tokens of any kind. Instead, Airlock 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. Airlock will only attempt to authenticate using cookies when the incoming request originates from your own SPA frontend.

インストールInstallation

Laravel AirlockはComposerでインストールします。You may install Laravel Airlock via Composer:

composer require laravel/airlock

次に、vendor:publish Artisanコマンドを使用して、Airlockの設定とマイグレーションをリソース公開します。airlock設定ファイルがconfigディレクトリに設置されます。Next, you should publish the Airlock configuration and migration files using the vendor:publish Artisan command. The airlock configuration file will be placed in your config directory:

php artisan vendor:publish --provider="Laravel\Airlock\AirlockServiceProvider"

最後に、データベースマイグレーションを実行してください。AirlockはAPIトークンを保存しておくデータベースを1つ作成します。Finally, you should run your database migrations. Airlock will create one database table in which to store API tokens:

php artisan migrate

SPAの認証のためにAirlockを活用しようと計画している場合は、app/Http/Kernel.phpファイル中のapiミドルウェアグループへ、Airlockのミドルウェアを追加します。Next, if you plan to utilize Airlock to authenticate an SPA, you should add Airlock's middleware to your api middleware group within your app/Http/Kernel.php file:

use Laravel\Airlock\Http\Middleware\EnsureFrontendRequestsAreStateful;

'api' => [
    EnsureFrontendRequestsAreStateful::class,
    'throttle:60,1',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

APIトークン認証API Token Authentication

lightbulb">Tip!! 皆さん自身のファーストパーティSPAを認証するためにAPIトークンを決して利用してはいけません。代わりに、Airlockの組み込みSPA認証を使用してください。{tip} You should not use API tokens to authenticate your own first-party SPA. Instead, use Airlock's built-in SPA authentication[#spa-authentication].

APIトークン発行Issuing API Tokens

APIリクエスト認証に使用するため、APIトークン/パーソナルアクセストークンをAirlockは発行します。APIトークンを利用するリクエストを作成する場合は、BearerトークンとしてAuthorizationヘッダにトークンを含める必要があります。Airlock 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\Airlock\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;
}

トークンを発行するには、createTokenメソッドを使用します。このcreateTokenメソッドはLaravel\Airlock\NewAccessTokenインスタンスを返します。APIトークンはデータベースへ格納される前に、SHA-256を使いハッシュされますが、NewAccessTokenインスタンスのplainTextTokenプロパティにより、平文の値へアクセスできます。トークンを生成したら、ユーザーへこの値を表示しなくてはなりません。To issue a token, you may use the createToken method. The createToken method returns a Laravel\Airlock\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の「スコープ」と同じように、Airlockは「アビリティ(能力)」をトークンへ割り付けられます。createTokenメソッドの第2引数として、アビリティの文字列の配列を渡してください。Airlock 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;

Airlockにより認証されたリクエストを処理するとき、そのトークンが特定のアビリティを持っているかをtokenCanメソッドで判定できます。When handling an incoming request authenticated by Airlock, you may determine if the token has a given ability using the tokenCan method:

if ($user->tokenCan('server:update')) {
    //
}

lightbulb">Tip!! 利便性のため、tokenCanメソッドは受信認証済みリクエストがファーストパーティSPAから送信されたとき、もしくはAirlockの組み込みSPA認証を使用している場合は常にtrueを返します。{tip} For convenience, the tokenCan method will always return true if the incoming authenticated request was from your first-party SPA and you are using Airlock's built-in SPA authentication[#spa-authentication].

ルート保護Protecting Routes

受信リクエストをすべて認証済みに限定し、ルートを保護する場合は、routes/api.phpファイル中のAPIルートに対してairlock認証ガードを指定する必要があります。このガードは受信リクエストが認証済みであると保証します。そのリクエストが皆さん自身のSPAからのステートフルな認証済みであるか、もしくはサードパーティからのリクエストの場合は有効なAPIトークンのヘッダを持っているかのどちらか一方であるか確認します。To protect routes so that all incoming requests must be authenticated, you should attach the airlock 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:airlock')->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();

// 特定トークンの破棄
$user->tokens()->where('id', $id)->delete();

SPA認証SPA Authentication

Laravelが提供するAPIを使用し通信する必要があるシングルページアプリケーション(SPA)へ、シンプルな認証方法を提供するためです。こうしたSPAはLaravelアプリケーションと同じリポジトリにあっても、もしくはVue CLIを使用して生成したSPAのように、まったく別のリポジトリに存在していてもかまいません。Airlock 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.

Airlockはこの機能の実現のためにトークンは一切使用しません。Laravelへ組み込まれているクッキーベースのセッション認証サービスを使用します。これにより、XSSによる認証情報リークに対する保護と同時に、CSRF保護・セッションの認証を提供しています。皆さんのSPAのフロントエンドから送信されるリクエストに対し、Airlockはクッキーだけを使用して認証を確立しようとします。For this feature, Airlock does not use tokens of any kind. Instead, Airlock 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. Airlock will only attempt to authenticate using cookies when the incoming request originates from your own SPA frontend.

設定Configuration

ファーストパーティドメインの設定Configuring Your First-Party Domains

最初に、どのドメインから皆さんのSPAがリクエストを作成するのか設定する必要があります。airlock設定ファイルの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 airlock configuration file. This configuration setting determines which domains will maintain "stateful" authentication using Laravel session cookies when making requests to your API.

AirlockミドルウェアAirlock Middleware

次に、app/Http/Kernel.phpファイル中のapiミドルウェアグループへ、Airlockのミドルウェアを追加する必要があります。このミドルウェアは皆さんのSPAから受信するリクエストが、Laravelのセッションクッキーを使用して確実に認証できるようにする責任を負っています。同時に、サードパーティやモバイルアプリからのリクエストに対し、APIトークンを使用した認証ができるようにしています。Next, you should add Airlock'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\Airlock\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のログインページで最初に/airlock/csrf-cookieルートへのリクエストを作成し、アプリケーションのCSRF保護を初期化しなくてはなりません。To authenticate your SPA, your SPA's login page should first make a request to the /airlock/csrf-cookie route to initialize CSRF protection for the application:

axios.get('/airlock/csrf-cookie').then(response => {
    // ログイン処理
});

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.

lightbulb">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ルートに対してairlock認証ガードを指定する必要があります。このガードは受信リクエストが認証済みであると保証します。そのリクエストが皆さん自身のSPAからのステートフルな認証済みであるか、もしくはサードパーティからのリクエストの場合は有効なAPIトークンのヘッダを持っているかのどちらか一方であるか確認します。To protect routes so that all incoming requests must be authenticated, you should attach the airlock 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:airlock')->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:airlock']]);

次に、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に対するモバイルアプリのリクエストを認証するために、Airlockトークンを使用できます。モバイルアプリのリクエストに対する認証手順は、サードパーティAPIリクエストに対する認証と似ています。しかし、APIトークンの発行方法に多少の違いがあります。You may use Airlock 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

まずはじめに、ユーザーのメールアドレス/ユーザー名、パスワード、デバイス名を受け取るルートを作成し、次にこうした認証情報を元に新しいAirlockトークンを受け取ります。このエンドポイントは平文のAirlockトークンを返し、それはモバイルデバイス上に保存され、それ以降の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 Airlock token. The endpoint will return the plain-text Airlock 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('/airlock/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.

lightbulb">Tip!! モバイルアプリケーションに対してトークンを発行するときにも、自由にトークンのアビリティを指定できます。{tip} When issuing tokens for a mobile application, you are also free to specify token abilities[#token-abilities]

ルート保護Protecting Routes

以前に説明した通り、ルートへairlock認証ガードを指定することで、受信リクエストをすべて認証済み必須にし、ルートを保護できます。通常、routes/api.phpファイルでこのガードを指定したルートを定義します。As previously documented, you may protect routes so that all incoming requests must be authenticated by attaching the airlock authentication guard to the routes. Typically, you will attach this guard to the routes defined within your routes/api.php file:

Route::middleware('auth:airlock')->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

テストをする時は、Airlock::actingAsメソッドでユーザーを認証し、トークンにアビリティを許可する指定を行えます。While testing, the Airlock::actingAs method may be used to authenticate a user and specify which abilities are granted to their token:

use App\User;
use Laravel\Airlock\Airlock;

public function test_task_list_can_be_retrieved()
{
    Airlock::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:

Airlock::actingAs(
    factory(User::class)->create(),
    ['*']
);

章選択

設定

明暗テーマ
light_mode
dark_mode
brightness_auto システム設定に合わせる
テーマ選択
photo_size_select_actual デフォルト
photo_size_select_actual モノクローム(白黒)
photo_size_select_actual Solarized風
photo_size_select_actual GitHub風(青ベース)
photo_size_select_actual Viva(黄緑ベース)
photo_size_select_actual Happy(紫ベース)
photo_size_select_actual Mint(緑ベース)
コードハイライトテーマ選択

明暗テーマごとに、コードハイライトのテーマを指定できます。

テーマ配色確認
スクリーン表示幅
640px
80%
90%
100%

768px以上の幅があるときのドキュメント部分表示幅です。

インデント
無し
1rem
2rem
3rem
原文確認
原文を全行表示
原文を一行ずつ表示
使用しない

※ 段落末のEボタンへカーソルオンで原文をPopupします。

Diff表示形式
色分けのみで区別
行頭の±で区別
削除線と追記で区別

※ [tl!…]形式の挿入削除行の表示形式です。

テストコード表示
両コード表示
Pestのみ表示
PHPUnitのみ表示
和文変換

対象文字列と置換文字列を半角スペースで区切ってください。(最大5組各10文字まで)

本文フォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

コードフォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

保存内容リセット

localStrageに保存してある設定項目をすべて削除し、デフォルト状態へ戻します。

ヘッダー項目移動

キーボード操作