認証にまつわる物語
私はシステムデザインが大好きです。ユーザーにとって優れたソフトウェアを生み出すための、細かな意思決定について考えることが好きです。
エンジニアとして、私はセキュリティを重視しています。安全でなかったり、攻撃によって損失が発生したりするソフトウェアは、役に立ちません。私は、いつでも確実に動作する製品を作りたいと考えています。
最近、あるAIスタートアップの認証機能の開発に携わりました。フロントエンドにはNext.jsを使用しました。Next.jsはフロントエンドとバックエンドを一つのコードベースに統合できるため、小規模なチームにとって非常に強力です。
このプロジェクトでは、ブラウザ内で認証トークンをどのように保存し、保護するかという点に注力しました。その解決策は、クッキー、特にHttpOnlyクッキーです。
なぜLocal Storageではなくクッキーを使うのか?
Local Storageは使いやすいですが、リスクがあります。JavaScriptから読み取ることができてしまうため、クロスサイトスクリプティング(XSS)攻撃に対して脆弱になります。もし悪意のあるスクリプトがサイト上で実行されると、ユーザーのトークンが盗まれてしまう可能性があります。
クッキーはこの問題を解決します。クッキーにHttpOnlyフラグを付与することができるからです。これにより、ブラウザに対して「このクッキーはHTTPリクエスト経由でのみ送信すること。JavaScriptには触れさせないこと」と指示できます。
攻撃者がJavaScriptを使ってクッキーを読み取ろうとしても、何も見えません。クッキーは攻撃者からは見えない状態のままですが、ブラウザは自動的にサーバーへクッキーを送信し続けます。
クッキーをさらに安全にするために、私は他に2つのフラグを使用しています。
• Secure: クッキーがHTTPS経由でのみ送信されることを保証します。 • SameSite=Lax: クロスサイトリクエストフォージェリ(CSRF)攻撃を防ぐのに役立ちます。
Next.jsでの実装方法:
バックエンド(FastAPI)をブラウザから隠したいと考えました。そこで、Next.jsをプロキシとして使用し、サーバー間通信(server-to-server)の構成を作成しました。
- ユーザーがNext.jsのServer Action経由でログインします。
- Server Actionが認証情報をFastAPIに送信します。
- FastAPIがNext.jsサーバーにトークンを返します。
- Next.jsサーバーがそのトークンをHttpOnlyクッキーに書き込みます。
- ブラウザはクッキーを保存しますが、読み取ることはできません。
ユーザーがデータを必要とするとき、Next.jsサーバーがクッキーを読み取り、ユーザーに代わってバックエンドと通信します。機密性の高いトークンがブラウザのJavaScript環境に触れることはありません。
この構成により、バックエンドを隔離し、ユーザーの安全性を高めることができます。
あなたはNext.jsのプロジェクトで認証をどのように扱っていますか?ぜひ皆さんのアプローチを聞かせてください。
