メモ > 技術 > フレームワーク: 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