LoginSignup
18
20

More than 5 years have passed since last update.

Laravel Passport keyファイルの扱い

Posted at

Laravel Passportをインストールしていくと
php artisan passport:installコマンドでstorage/内にoauth-public.keyoauth-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()とかソース見ないと分からない。

18
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
20