Laravel Passportをインストールしていくと
php artisan passport:install
コマンドでstorage/
内にoauth-public.key
とoauth-private.key
が作られる。
.gitignoreではデフォルトでは除く設定。
動作にはこのkeyファイルが必須。
これはどうしたらいいのか?を考える。
バージョン:Laravel 5.4とPassport 2.0。
gitリポジトリに入れる
非公開なら.gitignoreを修正してリポジトリに入れればいいだけ。
これが一番簡単。
keyファイルを別の場所に置きたい場合
Passportのソースを追っていく…
https://github.com/laravel/passport/blob/2.0/src/PassportServiceProvider.php
keyファイルが使われれてるのはmakeAuthorizationServer()とregisterResourceServer()
publicとprotectedなので継承して好きなように書き換えられる…。
app/Providers/PassportServiceProvider.php
に
<?php
namespace App\Providers;
use Laravel\Passport\PassportServiceProvider as ServiceProvider;
use Laravel\Passport\Bridge;
use Laravel\Passport\Passport;
use League\OAuth2\Server\ResourceServer;
use League\OAuth2\Server\AuthorizationServer;
class PassportServiceProvider extends ServiceProvider
{
/**
* Make the authorization service instance.
*
* @return AuthorizationServer
*/
public function makeAuthorizationServer()
{
return new AuthorizationServer(
$this->app->make(Bridge\ClientRepository::class),
$this->app->make(Bridge\AccessTokenRepository::class),
$this->app->make(Bridge\ScopeRepository::class),
'file://' . Passport::keyPath('oauth-private.key'),
'file://' . Passport::keyPath('oauth-public.key')
);
}
/**
* Register the resource server.
*
* @return void
*/
protected function registerResourceServer()
{
$this->app->singleton(ResourceServer::class, function () {
return new ResourceServer(
$this->app->make(Bridge\AccessTokenRepository::class),
'file://'.Passport::keyPath('oauth-public.key')
);
});
}
}
config/app.php
で
//Laravel\Passport\PassportServiceProvider::class,
App\Providers\PassportServiceProvider::class,
これで書き換えられるようになったので次はAuthorizationServer()を探す。
AuthorizationServerの__constructに渡すのは
https://github.com/thephpleague/oauth2-server/blob/master/src/AuthorizationServer.php
* @param CryptKey|string $privateKey
* @param CryptKey|string $publicKey
CryptKeyは…ファイルへのpathかファイルの中身を渡せばいいらしい。
https://github.com/thephpleague/oauth2-server/blob/master/src/CryptKey.php
S3にkeyを置いて Storage::cloud()->get('oauth-private.key')
でもいいけど毎回DLするのは無駄なのでローカルに保存する。
config/filesystems.php
の設定次第でStorage部分の書き方は変えられるけどS3をデフォルトにしてても動く書き方で。
完成版?
<?php
namespace App\Providers;
use Laravel\Passport\PassportServiceProvider as ServiceProvider;
use Laravel\Passport\Bridge;
use Laravel\Passport\Passport;
use League\OAuth2\Server\ResourceServer;
use League\OAuth2\Server\AuthorizationServer;
use Storage;
class PassportServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
collect(['oauth-private.key', 'oauth-public.key'])->each(function ($key) {
if (!Storage::disk('local')->exists($key)) {
Storage::disk('local')->put($key, Storage::cloud()->get($key));
}
});
$this->registerAuthorizationServer();
$this->registerResourceServer();
$this->registerGuard();
}
/**
* Make the authorization service instance.
*
* @return AuthorizationServer
*/
public function makeAuthorizationServer()
{
return new AuthorizationServer(
$this->app->make(Bridge\ClientRepository::class),
$this->app->make(Bridge\AccessTokenRepository::class),
$this->app->make(Bridge\ScopeRepository::class),
'file://' . Passport::keyPath('app/oauth-private.key'),
'file://' . Passport::keyPath('app/oauth-public.key')
);
}
/**
* Register the resource server.
*
* @return void
*/
protected function registerResourceServer()
{
$this->app->singleton(ResourceServer::class, function () {
return new ResourceServer(
$this->app->make(Bridge\AccessTokenRepository::class),
'file://' . Passport::keyPath('app/oauth-public.key')
);
});
}
}
別の方法
完成してから思い付いたけどkeyファイルDLするartisanコマンドでも作ってデプロイ時に実行するだけでもいいかも…。
public function handle()
{
collect(['oauth-private.key', 'oauth-public.key'])->each(function ($key) {
if (!Storage::disk('local')->exists($key)) {
Storage::disk('local')->put($key, Storage::cloud()->get($key));
}
});
}
保存先が storage/app/
になるのはどうせAuthServiceProvider.phpにroutes()書いてるので一緒に読み込み先も変えるようにloadKeysFrom()書けばいいだけ。
Passport::routes();
Passport::loadKeysFrom(storage_path('app'));
これ使うと上の方法でもmakeAuthorizationServer()部分が不要になる。
最終版
<?php
namespace App\Providers;
use Laravel\Passport\PassportServiceProvider as ServiceProvider;
use Storage;
class PassportServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
collect(['oauth-private.key', 'oauth-public.key'])->each(function ($key) {
if (!Storage::disk('local')->exists($key)) {
Storage::disk('local')->put($key, Storage::cloud()->get($key));
}
});
$this->registerAuthorizationServer();
$this->registerResourceServer();
$this->registerGuard();
}
}
ぐるぐると試行錯誤した結果これは不要だった…という結論。
デプロイ時に自動化できるならartisanコマンドで実行。
artisanコマンドにしなくてもこのくらいならAuthServiceProviderに書けば十分。
とにかくkeyファイルをstorageに置けばいいだけ。
こういう使い方も想定してるはずだけどドキュメントに書かれてないだけ。
loadKeysFrom()とかソース見ないと分からない。