Lumen の Auth・Guard・User 認証徹底解説(1)— Authentication ドキュメントは結局何をしているのか

Wake
By Wake2019年8月2日約 9 分で読了
Lumen の Auth・Guard・User 認証徹底解説(1)— Authentication ドキュメントは結局何をしているのか

Lumen で認証を扱い始めたばかりのころ、キーワードで Google を検索する以外に、いちばんよくやるのが公式の Authentication ドキュメントを開くことだと思います。そして僕と同じように、期待して開いて、結局よく分からないまま閉じることになります。Laravel の経験がないまま Lumen に触れた人にとって、このドキュメントは省略が多すぎて、まるで手がかりがありません。

認証のしくみ全体を詳しく説明する前に、まずはこの短い一枚の Authentication ドキュメントが結局何を言っているのかを、ざっくり説明します。

Authentication Service Provider

いまや DI(Dependency Injection)が当たり前の時代で、サービスを使う前にまず登録するのは、多くの PHP 開発者にとって反射のようなものになっています。ところが、公式の Authentication ドキュメントどおりに AuthServiceProvider を登録し終えたあと、次の段落を見て固まってしまう人が多いはずです。この意味のよく分からないコードは、いったいどこから出てきたのでしょう?

$this->app['auth']->viaRequest('api', function ($request) {
  // Return User or null...
});

どの単語も分かる気がするのに、なんだかしっくり来ません。たしかに、これが AuthServiceProvider の boot メソッドの中に書かれていて、サービスの起動時に動くコードだということは分かります。でも、具体的には何をしているのでしょう?

まあ、待ってください。焦らずに、いったん視点を引いて、大きな疑問はわきに置きましょう。公式の Authentication ドキュメント全体が説明している流れを、かみくだいて言うと、だいたいこんな感じです:

  1. システムに 認証サービス を登録する。
  2. サービスの起動時に、リクエストをチェックする門番 を用意する。
  3. そのチェックの途中で、ユーザーを見分ける必要があれば、返却用のユーザーオブジェクト を用意できる。
  4. 認証ミドルウェア(auth middleware)の中で、用意しておいた 門番 を呼び出して認証チェックを行う。

ここではまず、よくある疑問を簡単な Q&A の形で答えていきます。詳しい中身と流れは、後の記事で説明します。

Authentication ドキュメント Q&A

viaRequest 関数はどこから来たの?リクエストをチェックするという意味?

そうとも言えるし、そうでないとも言えます。コードのコメントから見ると、viaRequestvia Request というより via RequestGuard、つまり リクエストの門番 RequestGuard を通してリクエストを処理する、という意味に近いです。viaRequest を呼び出すと、RequestGuard を作るための関数が 登録 されます。実際の RequestGuard オブジェクトが作られるのは、その Guard が初めて解決(resolve)されるときで、それまでは作られません(この点は後の記事で詳しく説明します)。

viaRequest('api', …)api って…?

この api は、いま作っている API とは直接関係ありません。カスタマイズできる auth driver のキーで、理屈のうえでは好きな文字列に置き換えられます。ただし、config/auth.php 側も合わせて変更するのを忘れないでください。

viaRequest(…, callback) の後ろの callback って…?

ここでの callback は、ユーザーオブジェクトを返す ための関数です。公式ドキュメントのこの構成では、返されたユーザーオブジェクトには 2 つの役割があります:

  1. RequestGuard が、入ってきたリクエストを ユーザー として解決するのか、それとも ゲスト 扱いにするのかを判断できるようにする(null を返すとゲストとみなされます)。
  2. $request->user() を呼び出したときに、この関数が動いて ユーザーオブジェクト を取得する。

app['auth'] はどこから来るの?

ご存じのとおり、ServiceProvider の中の $this->app は Lumen Application オブジェクトそのものです。そして app['auth'] は、アクセスされたときに自動で生成される AuthManager オブジェクトです。先に app['auth'] へアクセスしていないかぎり、ここが初めてインスタンス化される場所のはずです。試しに、このコードの前後で isset($this->app['auth']) を書いて確かめてみてください。

では $this->app['auth']->viaRequest('api', callback) という一行全体の意味は?

かんたんに言うと、AuthServiceProvider が起動するとき、自動で作られた AuthManager を通じて RequestGuard の auth driver を登録し、そこに ユーザーを判定して、ユーザーオブジェクトを取得する ための callback を渡している、ということです。

実際に認証を行っているコードは、いったいどこにあるの?

公式の Authentication ドキュメントの構成では、2 か所あります。1 つめは、Authenticate Middlewarehandle 関数の中です:

if ($this->auth->guard($guard)->guest()) {
  return response('Unauthorized.', 401);
}

ここでは Guard(デフォルトの api Guard)を呼び出して、リクエストがゲストかどうかを判断し、そうであればアクセスを拒否します。

2 つめは、AuthServiceProviderboot メソッドの中です:

$this->app['auth']->viaRequest('api', function ($request) {
  // Return User or null...
});

ここで定義した ユーザーオブジェクトを返す callback が null を返すと、guard($guard)->guest()true になります —— ゲストとみなされてアクセスが拒否されます。逆に、ユーザーを返せば、リクエストはそのまま通ります。

おわりに

この記事が、公式の Authentication ドキュメントを理解する助けになったなら、僕としてはとても嬉しいです。もしまだ疑問が解けなくても、大丈夫です。これからの記事で、認証のしくみ全体をできるかぎり詳しく解きほぐしていきます。そのころには、また少し違う見方をお届けできればと思います。

カテゴリー:
Wake

Wake

著者について

趣味が高じてフロントエンドとバックエンドの技術を少しかじっているエンジニアです。大好きなプログラミングのほかに、バドミントン、ボードゲーム、読書、料理、ピアノも好きです。今は AI も積極的に使っています。