0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

APIキーは「発行のたびに古いものを消す」設計にする(Laravel Sanctum)

0
Posted at

顧客サイトから社内システムのAPIを呼ぶためのAPIキーを、管理画面から発行できるようにしたときの実装メモです。

要件: 1顧客につき有効なキーは常に1つだけ

SanctumのcreateToken()は呼ぶたびに新しいトークンを発行でき、1つのモデルに複数のトークンを持たせることもできます。しかし、顧客向けAPIキーでは「有効なキーは常に1つ」というシンプルなルールにしました。複数の古いキーが有効なまま残っていると、どれが今使われているキーか分からなくなり、失効させたいときに全部消せているか不安になるためです。

// app/Http/Controllers/Admin/CustomerApiTokenController.php
public function store(Customer $customer): RedirectResponse
{
    $this->authorize('update', $customer);

    $customer->tokens()->delete();
    $token = $customer->createToken('site-api')->plainTextToken;

    return redirect()
        ->route('admin.customers.show', $customer)
        ->with('status', 'APIキーを発行しました(このページを離れると二度と表示されません)。')
        ->with('plainTextApiToken', $token);
}

新しいキーを発行する前に、必ず$customer->tokens()->delete()で既存のトークンを全部消してからcreateToken()します。これにより「発行ボタンを押す=古いキーを失効させて新しいキーに切り替える」という、運用者にとって分かりやすい1つの操作になります。

平文トークンは1回しか手に入らない

Sanctumの仕様上、plainTextToken(実際にAPIリクエストのヘッダーに使う生の文字列)は、発行した瞬間のレスポンスでしか取得できません。DBには元の文字列のハッシュしか保存されないので、あとから「もう一度見せて」はできません。

このため、redirect()->with('plainTextApiToken', $token)でリダイレクト先の画面に1回だけ流し、ビュー側で「今回発行したキーです。この画面を離れると二度と表示されません」という警告と共に表示します。セッションのフラッシュデータは次のリクエストで消えるので、リロードすれば自然に見えなくなります。

失効も「削除するだけ」

public function destroy(Customer $customer): RedirectResponse
{
    $this->authorize('update', $customer);

    $customer->tokens()->delete();

    return redirect()
        ->route('admin.customers.show', $customer)
        ->with('status', 'APIキーを失効させました。');
}

発行と失効、どちらも$customer->tokens()->delete()を使っている点が対称的です。「今あるキーを全部消す」という同じ操作に、その後createToken()するかしないかの違いしかありません。実装がシンプルだと、レビューする側も「このコードが何をするか」を一目で把握できます。

authorize('update', $customer)で権限を1箇所に集約

APIキーの発行・失効は、顧客情報の編集権限(update)に相乗りさせています。専用の権限(customers.api-token.manageのようなもの)を新設することもできますが、「顧客を編集できる人なら、その顧客のAPIキーも管理できて当然」という業務ルールなら、既存の権限をそのまま使う方がシンプルです。権限の種類を増やしすぎると、後から見たときに「このリソースにはどんな権限があったか」を把握するコストが増えます。

まとめ

  • 顧客ごとに有効なAPIキーは1つだけにし、発行前に必ず古いキーを削除する
  • 平文トークンは発行直後の1回しか見えない。フラッシュデータで1回だけ画面に流す
  • 発行と失効を「トークン全削除+作るか作らないか」という対称的な実装にする
  • 新しい権限を安易に増やさず、既存の権限に相乗りできないか先に検討する

この記事はZennにも投稿しています。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?