Edited at

Laravel Passport CreateFreshApiToken を MultiAuth で間違って使うと死ぬ話

More than 1 year has passed since last update.

Laravel Passport の CreateFreshApiToken というミドルウェアを使うと、OAuth2 で API を公開しつつ、自サイトでも同じ API でアプリが作れますが、MultiAuth での使い方を間違えると死にそうなので書きました。


問題点

Consuming Your API With JavaScript には web ミドルウェアグループに追加する形で紹介されていますが、これをそのまま MultiAuth でやるとたぶん死にます。


Typically, if you want to consume your API from your JavaScript application, you would need to manually send an access token to the application and pass it with each request to your application. However, Passport includes a middleware that can handle this for you. All you need to do is add the CreateFreshApiToken middleware to your web middleware group:


Kernel.php

'web' => [

// Other middleware...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],



やべめのフロー


  1. 引数になにも指定せず CreateFreshApiToken を設定。

  2. 適当なガードを設定した auth ミドルウェアを通る。

  3. 認証が成功すると shouldUse が呼ばれ config('auth.defaults.guard') が 2.のガードに上書きされる。 #1 #2


  4. $request->user(null) が呼ばれる。(引数を指定していないため $guard == null となっている) #


  5. いろいろあって


  6. AuthManager.phpguard に 4. の null が渡る。 #


  7. $name = $name ?: $this->getDefaultDriver()$name == config('auth.defaults.guard') == 2.のガード となる。 #


  8. ガードはキャッシュされているので 2. で使った SesisonGuard が再利用される。 #


  9. SessionGuard ではログインに成功したユーザーをキャッシュしているので 2.で認証したユーザーが CreateFreshApiToken まで戻ってくる。 #1 #2


  10. 2.で認証したユーザーの ID が JWT に組み込まれ、エンコードされ cookie に書き込まれる #1 #2


  11. authミドルウェアに、driverpassport のガードを指定した API にアクセスする。


  12. 2.で認証したユーザーID が認証に使われる。 #1 #2


ここで、2.のガードのプロバイダーと、Passport認証を行う 11.のガードのプロバイダーが違う場合、死です。


対策

cookie に書き込まれる JWT にガード名、型情報、モデル名などのメタデータは載ってないので、CreateFreshApiToken が利用できるガードは一種類に限定されると思います。

なので MutliAuth 環境で CreateFreshApiToken を利用する場合は、そのガードを指定するほかないような気がします。

追記(2016/11/24)

ガードを指定しても結局 Passport を利用する別のガードを通ってしまうと(上のフローでいうと11.)死なので、現状 MultiAuth 環境で CreateFreshApiToken を利用するのは無理ゲーな気がしてきました。。。


そもそも論

これって開発用に使うものではなかろうか...