- Laravel Passportの動作をmacOSで確認したメモ
環境
macOS Sierra
APIサーバー
- Vagrant
- VirtualBox
- Laravel5.5
クライアントサーバー
- MacのPHPビルトインサーバー
MacのPHPバージョンを7.0にする
- Laravel5.5はPHP7.0以上が必須
brewを使用してPHP7インストール
brew update
brew install homebrew/php/php70
パス設定
- シェルの設定に追記後、反映
vi ~/.zshrc
export PATH="$(brew --prefix homebrew/php/php70)/bin:$PATH" <-1行追記する
source ~/.zshrc
確認
- PHP7.0を確認
php -v
PHP 7.0.22 (cli) (built: Aug 7 2017 14:07:27) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
APIサーバー(Laravel5.5)
Laravel5.5インストール
composer create-project --prefer-dist laravel/laravel Laravel-API-Auth-Sample dev-develop
プロジェクト直下にHomesteadインストール(vagrant)
composer require laravel/homestead --dev
php vendor/bin/homestead make
- 起動
vagrant up
- SSH接続
vagrant ssh
ユーザー認証(通常のユーザー作成準備)
- ユーザーテーブルSeeder作成
php artisan make:seeder UsersTableSeeder
データ追加処理
- ユーザーテーブルSeeder追記
database/seeds/UsersTableSeeder.php
<?php
use Illuminate\Database\Seeder;
use App\User;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
factory(User::class)->create([
'name' => 'テスト',
'email' => 'test@example.com'
]);
}
}
- DatabaseSeeder.phpのコメント解除
database/seeds/DatabaseSeeder.php
// コメントアウト
$this->call(UsersTableSeeder::class);
ログイン機能追加
- ログイン画面用のリソースなどが追加される
php artisan make:auth
API認証
passportインストール
composer require laravel/passport
Provider追記
config/app.php
/*
* Package Service Providers...
*/
// Laravel\Passport\PassportServiceProvider::class, // 1行追記
/*
* Application Service Providers...
*/
DB初期化
php artisan migrate
- UserSeederに記述したユーザーがusersテーブルに作成される
id 1
name テスト
email test@example.com
password secret
- OAuth用のテーブルが作成される
oauth_auth_codes
oauth_clients
oauth_personal_acces_clients
oauth_refresh_tokens
OAuth認証のユーザーを作成する
- 「user ID」 はusers.id を指定する
- callback用のURLを指定
- 「Client ID」,「Client secret」がoauth_clientsテーブルに追加される
$ php artisan passport:client
Which user ID should the client be assigned to?:
> 1
What should we name the client?:
> test
Where should we redirect the request after authorization? [http://localhost/auth/callback]:
> http://localhost:3333/callback.php
New client created successfully.
Client ID: 1
Client secret: cZ9W9ysdUFKlowO5d2CzzFFJ1uOBfggjv5Jx5cwr
クライアントサーバー(Macビルドインサーバー)
認証画面を通すやり方
- よくあるtwitterのアカウントで別サービスにログインする感じのやつ
oAuthサバーへアクセスする
get_token.php
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client as Client;
$guzzle = new Client;
$query = http_build_query([
'client_id' => '1',
'redirect_uri' => 'http://localhost:3333/callback.php',
'response_type' => 'code',
'scope' => '',
]);
header('Location: http://192.168.10.10/oauth/authorize?' . $query);
承認画面
- 「Authorize」ボタンを押下するとcodeパラメータ付きでコールバックURLに戻る
- 「Cancel」ボタン押下するとerrorパラメータ付きでコールバックURLに戻る
- 承認するとoauth_access_tokens, oauth_auth_codesテーブルにデータが格納される
コールバック
get_token_callback.php
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client as Client;
$http = new Client;
if ($_GET['code']) {
$response = $http->post('http://192.168.10.10/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => '1',
'client_secret' => 'cZ9W9ysdUFKlowO5d2CzzFFJ1uOBfggjv5Jx5cwr',
'redirect_uri' => 'http://localhost:3333/callback.php',
'code' => $_GET['code'],
],
]);
var_dump(json_decode((string)$response->getBody(), true));
}
出力結果
- 取得したaccess_tokenを使って外部API認証に使う
array(4) {
["token_type"]=>
string(6) "Bearer"
["expires_in"]=>
int(1296000)
["access_token"]=>
string(1071) "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImYxMmE0NDZkNmQxZjBlNzA4MWMwZWEwMzg5MDkxOWI1NWEzYzE5YTMxMGRlMGYwOWQ0ZjA4MmMzYTcxNGU1MzhmOGMzZTk3MzllZTc3OWQ1In0.eyJhdWQiOiIxIiwianRpIjoiZjEyYTQ0NmQ2ZDFmMGU3MDgxYzBlYTAzODkwOTE5YjU1YTNjMTlhMzEwZGUwZjA5ZDRmMDgyYzNhNzE0ZTUzOGY4YzNlOTczOWVlNzc5ZDUiLCJpYXQiOjE1MDQ2MDg2NTcsIm5iZiI6MTUwNDYwODY1NywiZXhwIjoxNTA1OTA0NjU3LCJzdWIiOiIxIiwic2NvcGVzIjpbXX0.kbvE4yrfGXcI4Bg0VW10-sDlFpsiG-_UB4uRIi_ylpB46kUkto3JdmlfWLINM83RWNrSkBdnzq6IYfPiHZY1wOw6qwObKG97pWhQVZO9yizVlZCe-ejRO-xv4do0QbXZQHzQqACwhSAYdQwymEJr3JqjrcaNUU8UV5wftlfLsDYNp-NVdo9hvq_7o49B79tIGG7F2izj0mmDHKXfhWLg5s8rFgkHw1q-Wn6o-YCMHgQhfWR9IVvJJ9bpywe45gcvse-MqaaFIQL4q-PHcSLAP0JHMrWLTHy0S2O-D10nWNE2XJyh3VPnxnKLH2jrGZpQVRpUN6RNQlftCxVJEoPruhyeE0Emb5KNJkwvFeIn2hEmLIseXqD4kuk0VESNlCz3VD0r6HRtvfpCTbHBK2uj_l69oYV0yUC6r_D-BfBK6ATZdTk-RIk3HV41ksMqOfpuSPymLoAieq_WqmU0i93VoACwoycirP6z1JTMuT4E1z8i_etgiodcOGpRWZQrePACURCxxGk1xGCaSRMVF_c42WNC5cw10wcHld9FToeFD4-KT_nBryz_eOMJ9Iw6foiyusRbR0vriGExOAesSiLpgLwnDEFBh3YpsDiOEVPvMJolMlVQ6tOnaUwyC3qunjrjVlbF9YR40r1b9DVJ7ZhhWGJNgYg0qadbNGt2uLIYscU"
["refresh_token"]=>
string(706) "def50200ce6524158569f59de11fd955552ae132336954dbd53dffc22544a3af145d1cc0b2b78c36b3c65c238c1486f24b3b551061591a84ec92d68d4438c62de3e6bcffa0df6ce1fa7ea127078a107390b8d3023897eff6cef63064e39b9376ab4ae4e685cc5b9b6b3ed67efe312de73c06458b78c6e7b8e6719d4e11cc9e57315ebb36b0b5e869ac9c0a8ae5f973e12ae2d26f61192d0532c7aeff90e6b7802fc6bd78a7303583bee7f14fabf31486e6431320e6f3d206c61af9dfb482b8195fb0577e9f5cefeb765742400aec2f3f9e16d3b70c5d21732347190bae5287cd13ad01f0b42e1cd3cfc51c193bfce2ffcb5b06f75224c1a7c6498657d2320fd44a78bc047b9bf2bdd17654b69ce9c74280d42bab8be6619be419ee84700d7086ff638a9b715290286906274bccbe9b876afb1b83382b2b2c9840423210e3b5ca4c9cab938391844e261ca6b247e88b3bc96b18d505784c87ef6932c1ed9dec7cc8"
}
認証画面なしでパスワード付きで外部からAPIを実行する
- 認証画面なしで外部からAPIを通してデータを保存したかったのでパスワード付きの認証にする
OAuth認証のユーザーを作成(APIサーバー)
- パスワードオプション付きでOAuthユーザー作成
- usersテーブルのidとは紐付けなくても良いみたい
# php artisan passport:client --password --name=password-user
Password grant client created successfully.
Client ID: 6
Client Secret: IzRQarKQ5y7b8Ni4Sf4nBvlDxeDAujm10lH6r3OW
API作成(APIサーバー)
- 外部からアクセスしてデータを保存するAPI
routes/api.php
Route::middleware('auth:api')->get('/memo', function (Request $request) {
$memo = $request->get('memo');
// SAVE MEMO...
return json_encode(array_merge(['status' => 'OK'], ['memo' => $memo . '-saved']));
});
クライアントサーバー(Macビルドインサーバー)
- OAuthユーザーのID, Secretを使用する
- 併せて通常のLaravelログインユーザーのID, Passwordも使用する
password_auth.php
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client as Client;
/**
* Class APIClient
*/
class APIClient {
/**
* @var Client
*/
protected $http;
/**
* @var
*/
protected $accessToken;
/**
*
*/
const API_SERVER = 'http://192.168.10.10';
/**
* APIClient constructor.
*/
public function __construct()
{
$this->http = new Client;
}
/**
* @param array $config
*/
public function auth(array $config = [])
{
$response = $this->http->post(self::API_SERVER . '/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => $config['client_id'],
'client_secret' => $config['client_secret'],
'username' => $config['username'],
'password' => $config['password'],
'scope' => '',
],
]);
$body = json_decode((string)$response->getBody(), true);
$this->accessToken = $body['access_token'];
}
/**
* @param string $memo
*/
public function save(string $memo = '')
{
$response = $this->http->request('GET', self::API_SERVER . '/api/memo', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '. $this->accessToken,
],
'query' => ['memo' => $memo],
]);
$body = json_decode((string)$response->getBody(), true);
if (isset($body['status']) && $body['status'] === 'OK') {
var_dump('saved memo');
}
}
}
// write .env etc
$config = [
'client_id' => '6',
'client_secret' => 'IzRQarKQ5y7b8Ni4Sf4nBvlDxeDAujm10lH6r3OW',
'username' => 'test@example.com',
'password' => 'secret',
];
$client = new APIClient;
$client->auth($config);
$client->save('ほげ');
// string(10) "saved memo" array(2) { ["status"]=> string(2) "OK" ["memo"]=> string(12) "ほげ-saved" }
参照
https://github.com/laravel/passport
https://laravel.com/docs/5.5/authentication#authenticating-users
https://laravel.com/docs/master/passport#introduction