Laravel 5.7 OAuth実装

Laravel5.7でOauth認証を実装します。
https://readouble.com/laravel/5.7/ja/passport.html

LaravelではPassportを使うことで、非常に簡単にOAuth2サーバの実装が可能になります。
Passportはleague/oauth2-serverというライブラリ上に構築されています。
cakephpなど他のフレームワークでも利用されており、信頼性の高いライブラリです。
https://oauth2.thephpleague.com/

実装

インストール

composerでインストールします。

composer require laravel/passport

Migration

client, accessTokenを格納するテーブルを作成します。
これもコマンド打つだけです。

php artisan migrate

accessToken生成のため、キーを作成しておきます。
強固なセキュリティにするため重要です。

php artisan passport:install

Model

Userモデルへ、traitを追加します。

User.php

namespace App;

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

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;

AuthServiceProvider

AuthServiceProviderへ、メソッドを追加します。
ここでAccessTokenの発行・失効を管理出来るようになります。

AuthServiceProvider.php

public function boot()
{
  Passport::routes();
}

設定

設定ファイルで、認証APIリクエストの方式を変更しておきます。
driverをpassportへ変更します。

config/auth.php

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

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

ルーティング

APIのルーティングを行います。
routes/api.phpで定義します。

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

もしくはコントローラに関連するアクションが下の方法で一度に定義可能です。

Route::group(['middleware' => 'auth:api'], function () {
    Route::resource('cotrollerName',  'ConditionController');
});

このとき設定されるアクションは以下が詳しいです。
https://readouble.com/laravel/5.7/ja/controllers.html#resource-controllers
ただし記載あるように不要なアクションも定義されてしまうので、実際は部分的なリソースルートとして定義が良いと思います。

接続テスト

Tokenの受け取りなど、APIのテストを行います。
Laravelに元々パッケージされている、ユーザ認証システムは実装済みの前提です。
※以下の「認証」のところまで
https://blog.shnr.net/?p=813

なおユーザーも作成済み、とします。

APIのテストには、Chrome addonのRestlet Client が便利でした。

https://chrome.google.com/webstore/detail/restlet-client-rest-api-t/aejoelaoggembcahagimdiliamlcdmfm

クライアントの登録

Oauthを実装する、クライアントを登録します。
grant typeはpasswordとします。

php artisan passport:client --password

成功すると、ID&secretが表示されるので、保管しておきます。

Password grant client created successfully.
Client ID: 2
Client Secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Request Token

アクセストークンのリクエストを行います。
トークンの有効期間は、AuthServiceProvider で設定した内容となります。

Method: POST
URL: youredomein.com/oauth/token
Header: [Content-Type: application/json;]
body:

{
    "grant_type": "password",
    "client_id": 2,
    "client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "username": "my.name@mail.com",
    "password": "test",
    "scope": "*"
}

Result:

{
"token_type": "Bearer",
"expires_in": 1296000,
"access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"refresh_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

無事にTokenが取得できました。
このTokenはその他のAPI接続で使うので、cookieなどに保管しておきます。

なおexpires_inは、tokenが無効になるまでの秒数とのこと。
AuthServiceProviderクラスのboot()で指定できます。

        Passport::tokensExpireIn(now()->addDays(15));
        Passport::refreshTokensExpireIn(now()->addDays(30));

※ただし認証時に正しくチェックされないとの情報あり(未検証)

Get user information

次にユーザー情報を取得します。
ヘッダーのAuthorizationで、アクセストークンを渡します。

Method: Get
URL: youredomein.com/api/user
Header: [Accept => application/json,
Authorization => Bearer xxxxxxxxxxxxxxxxx]

Result:

{
"id": 1,
"name": "My Name",
"email": "my.name@mail.com",
"email_verified_at": null,
"created_at": "2018-00-00 00:00:00",
"updated_at": "2018-00-00 00:00:00"
}

無事、ユーザー情報が取得できました。