Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Building a Full Enterprise-Ready React + Spring Boot Auth Flow: An End-to-End Guide

2026年08月22日に「Dev.to」が公開したITニュース「Building a Full Enterprise-Ready React + Spring Boot Auth Flow: An End-to-End Guide」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

ReactとSpring Bootを使った企業向け認証フローの安全な実装方法を解説。ログインからログアウトまで、httpOnlyクッキーによるトークン管理、CSRF保護、短命トークン更新、保護されたルーティングなど、セキュリティを強化した実践的な手順を網羅する。

ITニュース解説

認証は、ウェブアプリケーション開発において非常に重要でありながら、非常に複雑な機能の一つである。ユーザーが安全にサービスを利用できるように、そして不正アクセスからシステムを守るために、適切に実装する必要がある。しかし、シンプルなチュートリアルでは触れられない多くの落とし穴があり、それらを理解せずに本番環境で利用すると、重大なセキュリティ問題につながる可能性がある。この記事では、Reactをフロントエンド、Spring Bootをバックエンドとして利用し、エンタープライズレベルで通用するセキュアな認証フローを構築する方法を、一連の流れで詳しく説明する。

まず、この認証システムの全体像を理解しよう。ユーザーがログインするところから始まり、安全なトークンの発行と保存、ログインしているユーザーだけがアクセスできるページの保護、そしてトークンの有効期限が切れた際の更新、最終的なログアウトまで、すべてを網羅する。ReactフロントエンドとSpring Bootバックエンドが連携して、セキュアな環境を作り上げるのだ。

このシステムを設計する上で、いくつかの重要な決定がある。最も注目すべきは、「トークンをどこに保存するか」という点だ。認証後に発行されるトークンは、そのユーザーが誰であるかを証明する「身分証明書」のようなものであり、これを安全に保管することが極めて重要になる。ここでは「httpOnlyクッキー」を使う方法を採用する。httpOnlyクッキーとは、ウェブブラウザのJavaScriptから直接アクセスできないように設定されたクッキーのことだ。これにより、もし悪意のあるスクリプトがウェブページに埋め込まれてしまったとしても(クロスサイトスクリプティング、XSS攻撃と呼ばれる)、そのスクリプトからトークンが盗まれるリスクを大幅に減らすことができる。これは、localStorageにトークンを保存する方法よりもセキュリティが高いとされている。

しかし、httpOnlyクッキーを使うと、別のセキュリティ課題「クロスサイトリクエストフォージェリ(CSRF)攻撃」への対策が必要になる。CSRF攻撃とは、ユーザーが意図しない操作を、他のウェブサイトから強制的に行わせる攻撃のことだ。これを防ぐために、ここでは「ダブルサブミット/トークンパターン」というCSRF保護メカニズムを導入する。これは、バックエンドが特別なCSRFトークンを発行し、フロントエンドはそのトークンを読み取り、重要なリクエストの際にヘッダに含めてバックエンドに送り返すことで、正当なリクエストであることを確認する方法だ。このCSRFトークンはJavaScriptから読み取る必要があるため、httpOnlyではないクッキーとして発行される。攻撃者のサイトからはこのクッキーを読み取ることができないため、安全が保たれる仕組みだ。

さらに、発行するトークンの種類についても考慮する。「短命のアクセストークン」と「リフレッシュトークン」の組み合わせを利用する。アクセストークンは、実際のデータアクセスに使う「一時的な鍵」のようなもので、有効期限を短く設定する。これにより、もしアクセストークンが万が一盗まれても、その影響を受ける時間を最小限に抑えられる。アクセストークンが期限切れになったら、より有効期限の長いリフレッシュトークンを使って新しいアクセストークンを取得する。このとき、セキュリティを高めるために「リフレッシュトークンローテーション」という手法も導入する。これは、リフレッシュトークンを使うたびに新しいリフレッシュトークンを発行し、古いリフレッシュトークンを無効にする方法で、もしリフレッシュトークンが盗まれても一度しか使えないようにすることで、再利用攻撃を防ぐ効果がある。

具体的な認証フローの各ステップを見ていこう。

最初のステップは「バックエンドでのログインとトークン発行」だ。ユーザーがユーザー名とパスワードを入力してログインを試みると、Spring Bootバックエンドがこれらの認証情報を検証する。認証が成功したら、バックエンドはアクセストークンとリフレッシュトークンという2種類のJWTを生成する。このアクセストークンは、先ほど説明したように、httpOnly、secure(HTTPS接続時のみ送信)、path(どのパスでクッキーが有効か)、sameSite(CSRF対策)といった属性を持つクッキーとして、HTTPレスポンスヘッダを通じてフロントエンドに送信される。トークン自体はレスポンスボディには含まれないため、JavaScriptから直接アクセスできない。

次に、「バックエンドでのCSRF保護」の設定だ。Spring Securityには、CSRF保護を簡単に設定できる機能が用意されている。CookieCsrfTokenRepositoryというコンポーネントを使い、CSRFトークンをクッキーとして発行するように設定する。このCSRFトークンクッキーは、JavaScriptから読み取れるようにhttpOnlyではない設定にする。これにより、フロントエンドはこのCSRFトークンを読み取り、後続のリクエストに含めることができる。

その「フロントエンドでのHTTPクライアント設定」だ。React側では、axiosのようなHTTPクライアントライブラリを使うことになる。このクライアントにはwithCredentials: trueという設定を行う。これにより、ブラウザがHTTPリクエストを送信する際に、そのドメインのクッキーを自動的にリクエストに含めてくれるようになる。さらに、axiosの「インターセプター」機能を使って、すべてのリクエストが送信される直前に、CSRFトークンクッキーを読み取り、それをリクエストヘッダ(例えばX-XSRF-TOKENという名前のヘッダ)に追加する処理を記述する。これにより、バックエンドは受け取ったリクエストにCSRFトークンが含まれているかを確認し、CSRF攻撃ではないことを検証できる。

「フロントエンドでの認証状態の管理」は、httpOnlyクッキーの特性を考慮して行う。JavaScriptからアクセストークンに直接アクセスできないため、ReactのContext APIを使って、ユーザーが「ログイン済みであるか」という認証状態だけを管理する。実際のトークンをContextやReactの状態に保存するわけではない。アプリケーションが起動した際や、ログイン・ログアウトが成功した際に、バックエンドの特定のAPI(例えば/auth/me)にアクセスして、現在のセッションが有効かどうか、つまりクッキーに含まれるアクセストークンが有効かどうかを確認する。有効であればユーザー情報を取得し、Contextの認証状態を「ログイン済み」に更新する。ログイン時には、認証成功後に改めて/auth/meを呼び出し、ユーザーデータを取得して認証状態を更新する。ログアウト時には、バックエンドのログアウトAPIを呼び出した後、Contextの認証状態を「未ログイン」に戻す。

「フロントエンドでのルートの保護」も重要なステップだ。ログインしているユーザーだけがアクセスできるページ(例えばダッシュボードページ)を保護するために、ProtectedRouteというReactコンポーネントを作成する。このコンポーネントは、Contextから現在の認証状態(ユーザーがログイン済みか否か)を取得し、もしログインしていなければログインページにリダイレクトする。これにより、未認証のユーザーが直接URLを入力して保護されたページにアクセスしようとしても、それが防げる。

「トークンリフレッシュの処理」は、短命なアクセストークンを運用するために不可欠だ。アクセストークンが期限切れになると、バックエンドへのリクエストは401エラー(未認証)を返す。このとき、axiosのレスポンスインターセプターがそのエラーを捕捉する。インターセプターは、401エラーを受け取ったら、自動的にバックエンドのリフレッシュAPI(例えば/auth/refresh)にリクエストを送信する。このリフレッシュAPIは、リフレッシュトークンを使って新しいアクセストークンと新しいリフレッシュトークンを発行し、それらをクッキーとして更新する。リフレッシュが成功したら、最初に401エラーを返したリクエストをもう一度再試行する。これにより、ユーザーはセッションの切れ目を意識することなく、アプリケーションを使い続けることができる。もしリフレッシュも失敗した場合は、セキュリティ上の理由から強制的にログアウトさせ、ログインページにリダイレクトする。

最後のステップは「ログアウト」だ。httpOnlyクッキーはJavaScriptから直接削除できないため、ログアウト処理もバックエンド経由で行う必要がある。フロントエンドからログアウトリクエストをバックエンドに送信すると、Spring Bootバックエンドはアクセストークンのクッキーを有効期限を0にして再発行する。これにより、ブラウザは即座にそのクッキーを削除する。さらに、サーバー側で管理しているリフレッシュトークンも無効化する。これにより、完全にセッションが終了する。

これらの各ステップは独立しているように見えるが、実際には密接に連携し合って、堅牢な認証システムを構築している。一つでも欠けていると、セキュリティ上の弱点が生じる可能性があるため、それぞれの役割を理解し、適切に実装することが重要だ。

開発中に陥りやすい一般的な落とし穴とその対策についても触れておこう。CORS(クロスオリジンリソース共有)の設定ミスは、異なるドメイン間で通信する際にリクエストがブロックされる原因となる。withCredentialsオプションを設定し忘れると、クッキーがリクエストに送信されず認証が機能しない。長命なアクセストークンは、トークンが盗まれた際のリスクを高めるため、短命なアクセストークンとリフレッシュトークンの組み合わせを使うべきだ。リフレッシュトークンローテーションを行わないと、盗まれたリフレッシュトークンが何度も悪用される可能性がある。クッキーベースの認証でCSRF保護を怠ると、CSRF攻撃に脆弱になる。そして最も危険なのは、JWTをlocalStorageに保存することだ。これはXSS攻撃によって簡単にトークンが盗まれてしまうため、避けるべきである。

これらの点に注意し、各コンポーネントが連携して動作するこの認証フローを理解し実装することで、システムエンジニアを目指す初心者は、安全で信頼性の高いウェブアプリケーションを構築する上で非常に貴重な知識と経験を得ることができるだろう。この解説で紹介したコードサンプルは一般的なパターンを示しているため、実際の開発では使用しているライブラリのバージョンやデプロイ環境に合わせて、詳細なAPIや設定を適宜確認し、必ずご自身のセキュリティ要件に基づいてテストを行う必要がある。

関連コンテンツ

関連ITニュース