Help us understand the problem. What is going on with this article?

Laravel Passport keyファイルの扱い

More than 1 year has passed since last update.

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()とかソース見ないと分からない。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした