Memo

メモ > 技術 > フレームワーク: Laravel > API認証(API利用時にPassportでOAuth2認証)

■API認証(API利用時にPassportでOAuth2認証)
API認証(Passport) 5.5 Laravel https://readouble.com/laravel/5.5/ja/passport.html Laravel5.5でAPI認証のパッケージ(Laravel Passport)を利用する - Qiita https://qiita.com/niiyz/items/fffff94acb6061ecc9d4 Laravel5.6 PassportでAPI認証を実装 - Crunchtimer - Medium https://medium.com/crunchtimer/laravel5-6-passport%E3%81%A7api%E8%AA%8D%E8%A8%BC%E3%82%92%E5%AE%9F%E... Laravel PassportでWeb APIの認証を実装する【初期設定編】 | 大阪のシステム開発なら 株式会社ウィズテクノロジー https://www.whizz-tech.co.jp/1442/ Laravel PassportでWeb APIの認証を実装する【実装編】 | 大阪のシステム開発なら 株式会社ウィズテクノロジー https://www.whizz-tech.co.jp/1453/ ■インストール
$ composer require laravel/passport - Installation request for laravel/framework (locked at v5.5.44, required as 5.5.*) -> satisfiable by laravel/framework[v5.5.44]. - Installation request for laravel/passport ^7.0 -> satisfiable by laravel/passport[v7.0.0, v7.0.1, v7.0.2, v7.0.3].
インストールできない バージョンを指定してインストール
$ composer require laravel/passport=~4.0 - Installation request for paragonie/random_compat (locked at v9.99.99) -> satisfiable by paragonie/random_compat[v9.99.99].
インストールできない Your requirements could not be resolved to an installable set of packages - Issue #774 - laravel/passport https://github.com/laravel/passport/issues/774 composer - Laravel5.5のクライアント認証のためのパッケージがインストールできない|teratail https://teratail.com/questions/115287 を参考にrandom_compatとpassportのバージョンを指定してインストール
$ composer require paragonie/random_compat:2.* $ composer require laravel/passport=~4.0
インストールできた (passportのバージョン指定が無いと、相変わらずエラーになった) データベースにテーブルを作成(マイグレーションは /vendor/laravel/passport/database/migrations 内のファイルが実行されるみたい)
$ php artisan migrate Migrating: 2016_06_01_000001_create_oauth_auth_codes_table Migrated: 2016_06_01_000001_create_oauth_auth_codes_table Migrating: 2016_06_01_000002_create_oauth_access_tokens_table Migrated: 2016_06_01_000002_create_oauth_access_tokens_table Migrating: 2016_06_01_000003_create_oauth_refresh_tokens_table Migrated: 2016_06_01_000003_create_oauth_refresh_tokens_table Migrating: 2016_06_01_000004_create_oauth_clients_table Migrated: 2016_06_01_000004_create_oauth_clients_table Migrating: 2016_06_01_000005_create_oauth_personal_access_clients_table Migrated: 2016_06_01_000005_create_oauth_personal_access_clients_table
データベース管理ツールなどで、テーブルが作成されたことを確認しておく ■アクセストークンを作成 この作業により暗号キーが生成され、 oauth_clients テーブルに「パーソナルアクセス」クライアントと「パスワードグラント」クライアントも作成される
$ php artisan passport:install Encryption keys generated successfully. Personal access client created successfully. Client ID: 1 Client Secret: Dww67qb3VFgBf5eXasC5weRSR1nBN9wAZ5xbhGLB Password grant client created successfully. Client ID: 2 Client Secret: BGp9oHDnNRD3Q45rd8Zd4VBKJbCYuhOChjiolQld
■認証ユーザを作成 この作業により、oauth_clients テーブルに対象ユーザ用の認証情報が登録される
$ php artisan passport:client Which user ID should the client be assigned to?: > 1 What should we name the client?: > OAuth Test Where should we redirect the request after authorization? [http://localhost/auth/callback]: > http://localhost/~test/oauth/callback.php New client created successfully. Client ID: 3 Client secret: syHivsywmRTVTf0Cbh72u14ICDdntiDBzFHiLChc
■プログラムの修正 Userモデルに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; // HasApiTokensを追加 }
AuthServiceProviderに Passport::routes を追加
<?php namespace App\Providers; use Laravel\Passport\Passport; // 追加 use Illuminate\Support\Facades\Gate; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider { /** * アプリケーションのポリシーのマップ * * @var array */ protected $policies = [ 'App\Model' => 'App\Policies\ModelPolicy', ]; /** * 全認証/認可サービスの登録 * * @return void */ public function boot() { $this->registerPolicies(); Passport::routes(); // 追加 } }
config/auth.php の設定を変更
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', // tokenをpassportに変更 'provider' => 'users', ],
routes/api.php にテスト用APIを追加
Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); }); // テスト用API Route::middleware('auth:api')->get('/test', function (Request $request) { return json_encode(array_merge(['status' => 'OK', 'message' => 'test!'])); });
■認証クライアントを作成 「認証ユーザを作成」で作成したユーザで認証するプログラムを作成してみる 認証を開始するプログラム。ブラウザから直接アクセスする想定 http://localhost/~test/oauth/start.php
<?php $queries = array( 'client_id=3', 'redirect_uri=http://localhost/~test/oauth/callback.php', 'response_type=code', 'scope=', ); header('Location: http://blog.homestead.test/oauth/authorize?' . implode('&', $queries)); exit;
認証すると、以下にリダイレクトされる(実際はURLの後ろに「?code=XXXXX」のような値が付く) http://localhost/~test/oauth/callback.php
<?php session_start(); if (empty($_GET['code'])) { exit('Code is empty.'); } $result = file_get_contents( 'http://blog.homestead.test/oauth/token', false, stream_context_create( array( 'http' => array( 'method' => 'POST', 'header' => implode( "\r\n", array( 'Content-Type: application/x-www-form-urlencoded' ) ), 'content' => http_build_query( array( 'grant_type' => 'authorization_code', 'client_id' => '3', 'client_secret' => 'syHivsywmRTVTf0Cbh72u14ICDdntiDBzFHiLChc', 'redirect_uri' => 'http://localhost/~test/oauth/callback.php', 'code' => $_GET['code'], ) ) ) ) ) ); $json = json_decode($result, true); $_SESSION['access_token'] = $json['access_token']; header('Location: ./request.php'); exit;
アクセストークンを取得後、以下にリダイレクトされる http://localhost/~test/oauth/callback.php
<?php session_start(); if (empty($_SESSION['access_token'])) { exit('Access Token is empty.'); } $result = file_get_contents( 'http://blog.homestead.test/api/test', // テスト用API //'http://blog.homestead.test/api/user', // ユーザ情報取得API false, stream_context_create( array( 'http' => array( 'method' => 'GET', 'header' => "Accept: application/json\r\n" . "Authorization: Bearer " . $_SESSION['access_token'] . "\r\n" ) ) ) ); echo '<pre>' . $result . '</pre>'; exit;
以下のようにJSONが表示されれば成功(/api/user を呼び出した場合は、JSONでユーザ情報が表示される)
{"status":"OK","message":"test!"}
アクセストークンは oauth_refresh_tokens テーブルに access_token_id として記録される アクセストークンでAPIを呼び出すときは以下の箇所で認証情報を送信している
Authorization: Bearer " . $_SESSION['access_token'] . "
以下のようにBase64デコードを行うと、送信しているデータの内容を確認できる
echo base64_decode($_SESSION['access_token']); exit;
以下のような情報を確認できるが、このうち「2c7896d9f0809d4b77a531bd7562c9ce9146c9d9ed10e1c70fb88aaf9bd69f05c38ec60739e29d57」が access_token_id と一致する
{"typ":"JWT","alg":"RS256","jti":"2c7896d9f0809d4b77a531bd7562c9ce9146c9d9ed10e1c70fb88aaf9bd69f05c38ec60739e29d57"}以下略
Laravel における Bearer 認証 - chatbox blog https://www.chatbox.blog/2018/05/29/laravel-%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B-bearer-%E8%AA%8D%E8... Authorization Bearer ヘッダを用いた認証 API の実装 - げっとシステムログ https://www.getto.systems/entry/2017/10/19/004734 ■認証クライアントを作成 取得したアクセストークンをファイル内に直接書いておけば、任意のタイミングでAPIを呼び出せるようになる
<?php define('ACCESS_TOKEN', 'アクセストークンの内容'); $result = file_get_contents( 'http://laravel.homestead.test/api/test', false, stream_context_create( array( 'http' => array( 'method' => 'GET', 'header' => "Accept: application/json\r\n" . "Authorization: Bearer " . ACCESS_TOKEN . "\r\n" ) ) ) ); echo '<pre>' . $result . '</pre>'; exit;
■トークン持続時間 「デフォルトでPassportは、再生成する必要のない、長期間持続するアクセストークンを発行します。」とある 短くしたい場合はコードで指定する API認証(Passport) 5.5 Laravel https://readouble.com/laravel/5.5/ja/passport.html#configuration ■以下デバッグ時のメモ app/Http/Kernel.php に以下のコードは手動で追加した?不要かも?
'client' => CheckClientCredentials::class,
Laravel 5.5 API User Authentication with Passport Package https://www.itechempires.com/2017/09/laravel-5-5-api-user-authentication-passport-package/ Laravel 5.4でWeb APIを作る - アシアルブログ http://blog.asial.co.jp/1498 API Authentication Error: {"error":"invalid_client","message":"Client authentication failed"} - Issue #221 - laravel/passport https://github.com/laravel/passport/issues/221 PHP - Laravelで認証画面が表示されない|teratail https://teratail.com/questions/98712 Laravel5.5でAPI認証のパッケージ(Laravel Passport)を利用する - Qiita https://qiita.com/niiyz/items/fffff94acb6061ecc9d4

Advertisement