📝 BLOG.IK.AM

@making's memo
(🗃 Categories 🏷 Tags)

Spring Bootで作ったREST APIにFrontendからアクセスする際の認証/認可パターン

🗃 {Programming/Java/org/springframework/security}

🏷 Java 🏷 Spring Boot 🏷 Spring Security 🏷 Spring Session

🗓 Updated at 2017-06-25T15:21:50+09:00 by Toshiaki Maki  🗓 Created at 2017-06-25T09:20:36+09:00 by Toshiaki Maki  {✒️️ Edit  ⏰ History}


🚨 Warning: This content is old. Please don't trust too much.

目次

はじめに

Spring Bootで作ったREST APIにFrontend(ここでは画面を想定)からアクセスする際の認証/認可をどうするか。
Spring Bootに限るわけではないけど、今あるSpringスタックを使いこなすにはSpring Bootなしだと厳しい。

いくつか考えられるパターンがあるが、結論から言うと

  • 不都合ないならOAuth2
  • APIにアクセスするクライアントごとの認可制御が必要でないなら、Spring Session

が良い。

以下、いくつかのパターンのメリット・デメリットを挙げる。

サーバーサイドセッション

image

認証 認可
フォーム認証 Spring Security + JSESSIONID (Cookie)

これは普通のSpring Securityをサーバーサイドのテンプレートエンジンレンダリング(JSP, Thymeleaf)と一緒に使うのと同じパターン。
テンプレートエンジンの代わりに素のHTMLをアプリケージョンサーバーから返しても良いし、Thymeleafなどのテンプレートの中にJavaScriptを書いても良い。

メリット

フロントエンドとバックエンドを分ける必要がなく極めてシンプル。トークンの管理について気にすることはほとんどなく、サーバーサイドのセッション管理そのものである。一度ログインすればサーバーサイドセッションが切れるまで認証処理をする必要がない。

デメリット

APIにアクセスできるのは、このサーバーから返されたHTMLからだけであり、実質APIサーバーではない。フロントエンドとバックエンドを独立して開発したい場合は、バックエンドのビルド時にフロントエンドもビルドし、target/classes/staticフォルダの下にコピーして全部入りjarファイルを作る形になる。

API化というより、JavaScriptを駆使してアプリケーションのフロントエンドの使い勝手をよくしたいと言うケースであればこれで十分。

サーバーをスケールアウトする際は、Sticky Sessionにするか後述のSpring Sessionを使う必要がある。

Basic認証

image

認証 認可
Basic認証 Spring Security + Basic (Authorization Header)

普通のBasic認証。

メリット

シンプルでステートレス。設定も簡単。

デメリット

都度、ユーザー名:パスワードをBase64でエンコードしたものを送信するので、HTTPヘッダーが漏れた場合の影響は大きい。
また、認証もリクエストの度に発生する。

Basic認証より、Digest認証の方がエンコーディング方式がましだけど、その分JavaScript側でヘッダーを作成するのが面倒。

独自トークン

image

認証 認可
独自認証 独自認可 + 独自トークン (Authorization Header)

「Basic認証は嫌だから何かしらトークンを発行して、それをチェックする方式にしたい。けれどSpring Securityのカスタマイズ方法がよくわからない。」という時に取りがちなのがこの独自トークンパターン。

メリット

完全にカスタマイズ可能。最小限の機能から始められるので理解しやすい。

デメリット

Spring Securityが提供する様々なセキュリティ対策を使えない。独自トークンがセキュアかどうかは実装次第。
小さく始められるのは良いが、実装が進むにつれ、足りない機能が増えてきて、機能追加に不必要なコストがかかる。

OAuth2

image

認証 認可
フォーム認証 (Authorization Server) Spring Security OAuth2 + アクセストークン (Authorization Header)

いわゆるOAuth2。FrontがSingle Page Applicationの場合は、Implicit Flow、サーバーサイドレンダリングの場合はAuthorization Flowを使用する。
ログインはリダイレクトされたAuthorization Server側で行う。

Spring Security 5からはSpring Security側でOAuth2が対応される。

メリット

標準仕様なので、トークン発行のフローなどは共通知識として使える。対応クライアントも多い。
クライアントの登録・制御も可能で、API単位のスコープ制御ができる。
また、APIにアクセスしたいFrontendが増えた際は、Authrorization Serverを経由することでSingle Sign-Onができる。

Spring Security OAuth2を使うことでトークンのチェックや保存の方法を差し替えることもできる。

デメリット

OAuth2の知識が必要。また、他の方式に比べてAuthrozation Serverが必要なので、クライアントが1つしかない場合には少し大きい。
JWTを使用しない場合は、APIサーバーにアクセスする度にAuthorization Serverへのトークンチェック or ユーザー情報取得のためのリクエストが発生するので、
何らかのパフォーマンス対策の検討が必要ある。また、ログアウトも特殊になる。

Spring Session

image

認証 認可
Basic認証 Spring Security + Token (X-Auth-Token Header)

Spring Sessionを使う方法。Spring SessionはCookieにJSESSIONIDを設定する方法と基本的には同じ。
Spring SessionではトークンをCookieかHTTPヘッダーに設定することができる。REST APIの認可の場合はHTTPヘッダーを使うのが良い。

認証方式はBasicにしておき、はじめに任意のエンドポイントにBasic認証リクエストを送る。認証が成功すればHTTPレスポンスのx-auth-tokenヘッダーにトークンが設定されるので、
それ以降APIにアクセスする際のHTTPリクエストのx-auth-tokenヘッダーに取得したトークンをつければ良い。

メリット

独自トークン並みのシンプルさで、トークン発行の仕組みをSpring Sessionに任せられる。
トークンの保存先はRedis, MongoDB, JDBC, HazelCast, in-memory(テスト用)などから選択可能。

Spring Bootを使えばほとんど設定せずに使用できる。

OAuth2のようなクライアントやスコープの制御が不要であれば、Spring Sessionで十分だと思われる。

デメリット

Spring Sessionが用意されているものの、基本的には独自トークン方式なので、Spring以外のAPIサーバーとの

まとめ

再掲になるが、

  • 不都合ないならOAuth2
  • APIにアクセスするクライアントごとの認可制御が必要でないなら、Spring Session

が良い。

Spring Security OAuth2の学習コンテンツはこちら
Spring Sessionを使ったサンプルはこちら