spring boot(Java)で作成したREST APIをspring securityとkeycloakで保護する

はじめに

spring boot(Java)で作成したREST APIを、

keycloakとspring securityを連携させて保護する方法について解説します。

 

個人情報の取得、指定の口座に入金などのAPIの場合、

誰でもAPIが実行できてしまうのは大問題です。

 

スマホのアプリやWebサイトにログイン機能があるように、

APIにも認証済みクライアントから

呼び出された時だけ処理できるよう保護する必要があります。

 

このAPIの保護をkeycloakとspring securityでどのようにすればよいかをまとめました。

 

keycloakとは??keycloakでできることは??

色々記事が既に出てるのでこの辺りを参考にして頂くのが早いと思います。

>>keycloakとは

 

が、、、

一応簡単にkeycloakどんな感じで僕が業務で使ってるかを紹介すると、

 

ログイン機能、ユーザ管理の部分は完全にkeycloakに任せていています。

ログイン失敗連続したら30分ロックをかけるとか、

8桁以上の英数字混合のパスワードでないとパスワードポリシーとしてダメ

などのよくあるセキュリティ要件もkeycloakでポチポチやるだけで実現できるのでかなり工数削減できたりします。

こんな感じ

 

 

あとは、

自前で立ててる認証認可基盤やFacebookやTwitterに

認証を移譲させるようなSSO(Single Sign On)が出来たりとか、

OAuth2.0やOpenID Connect(OIDC)といった

access tokenやid tokenを発行するための仕様を満たす

認証認可基盤としても利用できます。

 

access tokenを発行するためのOAuth2.0という仕様の全体概要については、

こちらの記事にまとめたので興味のある方はご覧ください。

認可コードフローを図解|OAuth2.0(OIDC)の仕組みをSPAのSSO機能を例に解説

 

あと、オープンソースソフトウェアなので無料で使えます。

 

 

keycloakとspring securityでspring bootで作ったREST APIを保護??

keycloakとspring securityでAPIを保護するざっくり全体の流れを図にするとこんな感じです。

 

 

①でクライアントはまずkeycloakとやりとりして、

keycloakからaccess tokenというものを発行してもらいます。

(access token発行までの流れについては本題ではないのでここでは触れません。)

 

access token発行までの流れが気になる方はこちらの記事を参照ください。

認可コードフローを図解|OAuth2.0(OIDC)の仕組みをSPAのSSO機能を例に解説

 

access tokenは、このクライアントはAPIを利用してもOKという証明になります。

②でAPIを呼び出すクライアントはこの証明を付けて呼び出します

(リソースエンドポイントをコールします)。

 

これを受け取ったREST APIはspring securityでこの証明って正しい??有効??

というのをkeycloakに対して確認(トークン検証)します。

この確認のことをトークンイントロスペクションと言います。

 

keycloakがこの確認で問題なしと答えた場合に初めて④のリソースの返却をします。

(問題ありの場合はAPIのレスポンスは401 認証情報不足エラー)

 

これによって、正しいアクセストークンが発行されたクライアントだけAPIが利用できることになります。

つまり、APIが保護できることになります。

 

Spring Bootで作成したREST APIをkeycloakとspring secutiryで保護する具体的な手順解説

githubにソースコードを公開しておいたので、

ローカル環境で動作確認したい場合はそちら参照ください。

(READMEに記載の通り、

dockerをインストールして、docker上でkeycloakを8180ポートで立ち上げるような形になります)

>>poc-spring-vue3-keycloak

 

keycloakでaccess token発行とトークンイントロスペクションの設定

 

keycloakの設定としては大きく3つ行います。

1.トークンイントロスペクション用のclient作成

ここで作成するclientをspring securityが使います。今回はtokenintrospectionという名前のclientを作成しました。

 

 

クライアントの種類としてはcredentialとし、

secret情報を使ってkeycloakとspring securityがやりとりできるようにしておきます。

そのため、secret情報はこのあとspring側の設定ファイルに記載します。

 

 

2.access tokenを発行する際に利用するclientの作成

先ほどの図の①でaccess tokenを発行してもらう際には、

今回は別のクライアントを利用します。名前はfrontendとしました。

 

今度はクライアントの種類としてpublicとしてsecret情報を利用せずに

keycloakとやりとりするようにしておきます。

(SPAでフロントエンドからkeycloakとやりとりをする際はこのような

設定のclientを使うのでそんな想定のやつです)

 

 

3.APIの利用を許可するユーザの作成

次に、APIを利用できるようにするユーザを作成します。

テキトーでいいです。今回はID/PASSどちらもsample001というユーザを作成しました。

 

 

ちなみに、

公開しているgithubの通りにkeycloakを立ち上げるとこの辺り

設定済みの状態からスタートできるようにしてます。

 

spring securityでaccess tokenをトークンイントロスペクションで検証する設定

次はspring security側の設定です。こちらも設定のポイントは3点です。

 

spring securityのresource serverライブラリを入れる

(mavenなんですが、、、)コードで言うとこの辺りです。

>>github該当箇所

 

tokenintrospectionへのアクセス情報をプロパティに追加する

コードで言うとこの辺りです。

>>github該当箇所

 

tokenintrospectionできるようにSecurityConfigクラスを作成する

コードで言うとこの辺りです。

>>github該当箇所

 

ここではhealthと言うエンドポイントはアクセストークンなしでも呼び出せる設定にして、

そのほかのエンドポイントはアクセストークンが正しくなければ呼び出せないようにしています。

今回はhealthとhelloの2本のAPIを作成していて、

helloはアクセストークン付きリクエストされないと401エラーを返すようにしています。

 

MEMO

APIを作成して本番運用する際、

全エンドポイントにおいて、アクセストークン必須にしてしまったせいで、

死活監視(APIサーバがちゃんと動いてるかチェックするイメージ)が。。。。

ってならないようにAPIを保護から除外する設定も覚えておきましょう。

 

APIは今回healthとhelloの2本を作成しています。

 

 

spring securityとkeycloakでSpring Bootで作成したREST APIが保護される動作確認

ここからは動作確認を4パターンしていきます。

 

health check用のAPIがaccess tokenなしで動作する確認

これはブラウザでAPIのエンドポイントをコールすれば確認できます。

 

 

保護対象のAPIはaccess tokenなしで401エラーとなることの確認

これもブラウザでAPIのエンドポイントをコールすれば確認できます。

 

 

保護対象のAPIはaccess tokenが正しいとき正常に動作することの確認

ここからはブラウザだとダメで。。。

curlコマンドかクライアントツールを使う必要があります。

 

ここではchromeの拡張機能のTalend API Testerを使います。

使いたい方はこの辺り参考にしてみてください

>>Chrome拡張のTalend API TesterでAPIテスト

 

まず、keycloakからfrontendクライアントを利用して

sample001ユーザに対してアクセストークンを発行してもらいます。

(上の図でいう①のところ)

 

 

返却されたレスポンスのaccess_tokenをコピーします。

 

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ・・・",
"expires_in": 180,
"refresh_expires_in": 180,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ・・・",
"token_type": "Bearer",
"id_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJYNGZ・・・",
"not-before-policy": 0,
"session_state": "a8c7af29-d11f-4a71-9ec1-87ef94380ed3",
"scope": "openid profile"
}

 

コピーしたaccess_tokenをAuthorizationヘッダの「Bearer 」の後ろに貼り付けて

hello APIをコールすると正しくレスポンスが返却されます。

 

 

保護対象のAPIはaccess tokenが偽造されたとき401エラーとなることの確認

先ほど、「Bearer 」の後ろに貼り付けたアクセストークンをちょっと変更してAPIを呼び出します。

 

 

そうするとinvalid_tokenエラー(error_description=”Provided token isn’t active)

となることが確認できます。

第三者がユーザを偽装してアクセスしてきてもkeycloakとspring securityの保護で

弾けるということです。

 

まとめ

keycloakとspring secutiryを利用してspring bootで作成したREST API(java)を

保護する方法について解説しました。

改めて、ポイントは以下です。

 

keycloakの設定ポイントとしては

APIを利用したいユーザ作成、アクセストークン発行用、トークンイントロスペクション用のclient作成

 

spring securityの設定ポイントとしては

トークンイントロスペクション用のclient情報の設定、ライブラリ利用設定、SecurityConfigクラス作成

 

もしAPIの製造を担当することがあれば、

どんな感じで保護しているか??少し気にしてみてみてください。多分こんなことやってると思います。

 

SPAにKeycloakのSSO機能でログイン機能を追加、

OIDCやOAuth2.0の違い解説などなどをまとめたまとめ記事を作りました。

興味のある方は是非みてください!!

keycloakでAPI保護・SPAログイン機能設定例、OIDC・OAuth・PKCE・認可コードフロー図解などまとめ

 

 

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください