tech. tt

Teens Town 技術ブログ

LaravelでAPI認証基盤を作成

本記事ではLaravel推奨のOAuthライブラリPassportを用いて安全なOAuthサーバーを実装していきます。

公式マニュアル&標準ではWeb(Laravel Blade)経由でのユーザー登録ですが、今回はAPIによる登録を実装していきます。

Passportのインストール

Passportとは、LaravelにOAuth2.0を安全に実装できる外部ライブラリです。公式サイトにもガイドがあるのでほぼ公式ライブラリと言っても良いでしょう。

composer require laravel/passport でインストールできます。

インストール後、Passportはデータベース構造の情報(マイグレーションファイル)を生成するので、それを自分のデータベースに反映させてあげましょう。

php artisan migrate で反映できます。

その後php artisan passport:install を実行して完了です。

既存ファイルの書き換え

公式マニュアルに「このコマンドを実行後、App\User モデルへLaravel\Passport\HasApiTokens トレイトを追加してください。」とあるので、指示通りトレイトを追加します。

<?php

namespace App;

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;
}

次にapp/Providers/AuthServiceProvider.php を下記のように修正します。

    public function boot()
    {
        $this->registerPolicies();

        // 追加
        Passport::routes();
    }

最後に、config/auth.php でapi認証のドライバをpassportへ変更します。Authentication Guardsの項です。

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'passport', // 修正
            'provider' => 'users',
            'hash' => false,
        ],
    ],

API仕様に修正

Authディレクトリの移動

app/Http/Controllers/Auth にはLaravelに標準で搭載されている認証基盤が含まれています。

これらを、将来の仕様変更を見据えてディレクトリを移動しておきます。ここではapp/Http/Controllers/V1/Console/Authに移動させます。

ただディレクトリを移動させただけではnamaspaceが不整合になるので、各ファイルのnamespace設定をnamespace App\Http\Controllers\Auth からnamespace App\Http\Controllers\V1\Console\Auth へ変更します

RegisterController.phpの書き換え

先ほど移動したapp/Http/Controllers/V1/Console/Auth/RegisterController.php を下記のように修正します。

// 冒頭に追記
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Auth\Events\Registered;

// ...中略...


    public function register(Request $request)
    {
        // バリデート
        $validate = $this->validator($request->all());
        if ($validate->fails()) {
            return new JsonResponse($validate->errors(), 406); // エラー時は406 Not Acceptable を返す
        }

        // ユーザー登録
        event(new Registered($user = $this->create($request->all())));
        return new JsonResponse($user);
    }

また、コンストラクタにてguestミドルウェアが設定されているので、これを解除します。

    public function __construct()
    {
        // $this->middleware('guest');
    }

ルーティングの修正

最後にroutes/api.php を以下に書き換えます。

ルーティングの内容は手元の環境のnamespaceにあわせてください。
Route::group(["middleware" => "api"], function () {
    // 認証ルート
    Route::post('/register', '\App\Http\Controllers\V1\Console\Auth\RegisterController@register');
    /**
     * 認証済みルート
     */
    Route::group(['middleware' => ['auth:api']], function () {
        Route::get('/user', function (Request $request) {
            return $request->user();
        });
    });
});

登録機能テスト

では実際にAPI経由で登録できるか試してみます。

curlをずっと叩くのも手間ですので、今回はPostmanを利用します。インストール方法は省略。

URL入力欄にhttp://{localdomain}/register を入力し、その左でメソッドをPOSTに設定

次にBodyタブで form-data を以下のように指定し、送信! ※password_confirmation はパスワード確認の再入力項目です。一致しないとエラーを吐きます。

成功するとResponseとして新規ユーザー情報が返ってくるかと。

f:id:up-tri:20200219142954p:plain

ちなみに失敗すると406ステータスと共にエラーの原因が返ってきます。 ※この例はパスワードの不一致 f:id:up-tri:20200219143030p:plain
以上で登録機能を実装できました。

認証テスト

ユーザー登録が実装できたので、次はAPI認証に触れていきます。

API認証は標準で搭載されいるものを利用します。

はじめにAPI認証のクライアントを生成します。ターミナルでphp artisan passport:client --passwordを実行します。(名前を聞かれますので適当に入力しておいてください。)このコマンドでClient IDとClient Secretが生成されます。

URL入力欄にhttp://{localdomain}/oauth/token を入力し、下記のようなパラメータでPOST送信します。

f:id:up-tri:20200219143057p:plain

認証に成功すれば下記のようなJSONが返ってきます。

{
    "token_type": "Bearer",
    "expires_in": 31622400,
    "access_token": " ... ",
    "refresh_token": " ... "
}

無事に認証できたら、最後にAPI経由で自分のプロフィールを取得してみます。

URL入力欄にhttp://{localdomain}/v1/console/user を入力します。今回はHeaderにAuthorizationヘッダBearer {access token} という内容で追加します。BearerとAccess Tokenの間のスペースをお忘れ無きよう。

GETメソッドで下記のように通信できれば成功です!お疲れ様でした。

f:id:up-tri:20200219143115p:plain