シングルサインオンについて調べる機会がありkeycloakを使用してみたので、忘れないうちにまとめておきます。
環境
- Java(jdk 1.8.0_221)
- docker desktop(2.1.0.3)
- eclipse(2019-06)
– Spring Tools 3(3.9.11) - keycloak(12.0.4)
最終的にできあがるもの
- 認証サーバー(keycloak)
- サーバーアプリケーション(API)
– 認証が必要な機能がある - クライアントアプリケーション
– 上記APIを呼び出して使用する画面
– 一回のログインでAPIが利用可能になる
インストール
公式サイトの Get started with Keycloak on Docker を参照して導入します。
https://www.keycloak.org/getting-started/getting-started-docker
コマンド:
docker run -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:12.0.4
※環境変数の「KEYCLOAK_USER」「KEYCLOAK_PASSWORD」の値で管理者ユーザが作成されます。
管理画面へログイン
インストールが完了したらkeycloakへログインします。
http://localhost:8080/auth/admin
ログインIDとパスワードはコマンドで指定した管理者ユーザです。
※ログイン成功後にパスワード変更の警告が出ましたが(adminだから?)、無視して進めます。
日本語化
「Realm Settings」→「Themes」の「Internationalization Enabled」をONにし、
「Default Locale」で「ja」を選択してSaveします。
※Saveした直後は反映されません。左上のロゴをクリックしてトップページへ遷移し、
もう一度管理画面へ入ると反映されます。
レルム作成
左上の「Master」にマウスオーバーすると、「レルムの追加」ボタンが表示されるので押下します。
名前を入力して作成ボタンを押下します。
ロール作成
左メニューから「ロール」を選択し、ロールの追加ボタンを押下します。
ロール名を入力し保存ボタンを押下します。
ユーザ作成
左メニューから「ユーザー」を選択し、ユーザーの追加ボタンを押下します。
ユーザー名、名、姓に入力し保存ボタンを押下します。
パスワード設定
ユーザー作成後、詳細画面へ遷移するので「クレデンシャル」タブを表示しパスワードの設定を行います。
「一時的」項目をオンにしておくと、初回ログイン時にパスワード変更が求められます。
今回は必要ないのでオフにします。
ロール設定
「ロールマッピング」タブを表示しロールの設定を行います。
「user」ロールをアサイン済みロールへ移動させます。
ユーザー作成確認
アカウント管理画面を表示し、先ほど作成したユーザーでログインします。
http://localhost:8080/auth/realms/myrealm/account
ログインできました。
keycloakクライアント作成
keycloakを使用するクライアントを追加します。
この時点で実際のアプリケーションは作成していなくてもOKです。
左メニューから「クライアント」を選択し、作成ボタンを押下します。
クライアントID、クライアント・プロトコル、ルートURLを入力して保存ボタンを押下します。
サーバーアプリケーション作成
まずはSpting BootでAPIを作成します。
今回はquickstartsのservice-springboot-restをまるごと使用するのでgithubから持ってきます。(latestブランチ)
https://github.com/keycloak/keycloak-quickstarts/tree/latest/service-springboot-rest
このサービスには下記2つのエンドポイントがあります。
- public: 認証なしで呼び出すことができる
- products: 「user」ロールのユーザーのみ呼び出すことができる
application.properties変更
githubから持ってきたソースのapplication.propertiesを変更します。
server.compression.enabled: true server.compression.min-response-size: 1 server.connection-timeout=5000 server.port = 8081 ※8080はkeycloakで使用しているので8081 keycloak.realm=myrealm ※先ほど作成したレルム keycloak.auth-server-url=http://localhost:8080/auth ※keycloakのURL keycloak.ssl-required=external keycloak.resource=myclient ※先ほど作成したkeycloakクライアント keycloak.public-client=true keycloak.bearer-only=true keycloak.securityConstraints[0].securityCollections[0].name = protected resource keycloak.securityConstraints[0].authRoles[0] = user ※作成したロール keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /products keycloak.securityConstraints[0].securityCollections[0].patterns[1] = /products/
keycloakクライアント変更
先ほど作成したkeycloakクライアントを変更します。
アクセスタイプを「bearer-only」、管理URLを「http://localhost:8081/」(サーバーアプリケーションのURL)に変更しました。
動作確認
public(http://localhost:8081/public) を呼び出してみます。
値が返却されました。
products(http://localhost:8081/products) を呼び出してみます。
401エラー(アクセス権限なし)になりました。
クライアントアプリケーション作成
次に、先ほど作成したサーバーアプリケーションを利用するるクライアントアプリケーションを作成します。
こちらもgithubのquickstartsのapp-springbootを使用します。(latestブランチ)
https://github.com/keycloak/keycloak-quickstarts/tree/latest/app-springboot
下記2つのページがあります。
- public: 認証なしで表示できる
- product: 認証が必要なAPI(上記で作成したサーバーアプリケーション)から値を取得して表示する
application.properties変更
githubから持ってきたソースのapplication.propertiesを変更します。
server.compression.enabled: true server.compression.min-response-size: 1 server.connection-timeout=5000 spring.freemarker.cache=false server.port = 8082 ※8082を指定 keycloak.realm=myrealm ※作成したレルム keycloak.auth-server-url=http://localhost:8080/auth ※keycloakのURL keycloak.ssl-required=external keycloak.resource=myclient2 ※新しく追加するkeycloakクライアント(この後作成) keycloak.public-client=true product.service.url=http://localhost:8081/products ※先ほど作成したサーバーアプリケーションのproductのURL
keycloakクライアント追加
クライアントアプリケーション用のkeycloakクライアントを追加します。
先ほどと同じようにクライアントの作成ボタンから追加します。
動作確認1
実行しようとすると、エラーになりました。
java.lang.ClassNotFoundException: org.apache.http.client.methods.HttpUriRequest
pom.xmlの「httpclient」のscopeがtestになっているのが原因のようです。
scopeタグを消します。(masterブランチを確認したらscopeタグは削除されていたので、latestにもそのうち反映されるかも?)
pomの修正後、public(http://localhost:8082/) へ、アクセスしてみます。
画面が表示されました。
productsへ遷移してみます。
エラーになりました。設定が間違っているようです。
githubのreadmeのサンプルをそのまま採用したのが問題でした。
下記の設定を修正します。
※「8082/app-springboot」の「app-springboot」を削除します。
もう一度、productsへ遷移してみます。
ログイン画面にリダイレクトしました。
作成したユーザーでログインしてみます。
表示されました。
一旦ログインに成功したので、その後はログイン画面なしでAPIから値が取得されます。
動作確認2
ユーザーからロール「user」を外し
productsへ遷移してみます。
403エラー(閲覧禁止)になりました。
正常に認証できていることが確認できました。
最後に
シングルサインオンの調査の一環でkeycloakを使用しました。
実際にkeycloakが採用されるかはわかりませんが、
いざという時に今回の環境をベースにして使い方を学ぶ事ができると思います。