KeycloakでOpenID Connectを使ってみる(Spring Bootアプリケーション編)


概要

Keycloakアドベンドカレンダー3日目は、Spring BootベースのWebアプリケーションの認証をKeycloakに委譲する手順について説明します。KeycloakにはSpring Boot用のアダプターがあり、簡単にSpring BootベースのWebアプリケーションをセキュリティ保護できます。これにより、最新の認証プロトコルである「OpenID Connect」(以下OIDC)に対応したセキュアなSpring Bootアプリケーションとなります。

連携ができると、ユーザーはOIDCの「End User」に、Spring BootベースのWebアプリケーションはOIDCの「Relying Party」に、KeycloakはOIDCの「OpenID Provider」になります。

はじめる前に

このチュートリアルの操作をはじめる前に、Keycloakのセットアップを完了し、管理者ユーザーを作成する必要があります。Keycloakアドベンドカレンダー2日目の記事を参考にそれらの作業を実施しておいて下さい。また、Webアプリケーションのビルドと起動にGradleかMavenを使用しますので、いずれかをインストールしておいて下さい。

なお、今回はKeycloakもSpring BootベースのWebアプリケーションもlocalhostに構築します。

連携の手順

連携の手順は以下のようになります。これが完了したら、動作確認をします。

  1. Keycloakの設定
    • 1.1. レルムの作成
    • 1.2. クライアントの作成
    • 1.3. ロールの作成
    • 1.4. ユーザーの作成とロールの割り当て
  2. 簡単なSpring Bootアプリケーションの作成
    • 2.1. Spring Initializrでアプリの雛形作成
    • 2.2. クラスとhtmlの作成
    • 2.3. アプリのKeycloak連携の設定

1.1. レルムの作成

レルムを作成する前にレルムについて簡単に説明します。Keycloakにおける「レルム(Realm)」とは、ユーザー、ロール、接続するデータストア(LDAPなど)などをまとめるための範囲を意味します。ユーザーは、レルム内に作成することができ、認証の方法などをレルム単位で定義することができます。デフォルトでは、「Master」というレルムが一つあり、その後追加する全てのレルムを包含して管理することができます。「Master」レルムは、レルムの階層内で最も高いレベルであり、スーパー管理者(初回セットアップ時に作成した管理者アカウント)で管理できます。

「Master」レルムを使ってユーザーなどを管理することもできますが、基本的にはレルムを作成することが推奨されているので、まずはレルムを作成します。なお、「Master」レルムは削除することもできます。

http://localhost:8080/auth/admin/にアクセスして、管理者アカウントでKeycloak管理コンソールにログインします。

左側の一番上コーナーにある「Master」と表示されたドロップダウン・メニューで、「レルムの追加」をクリックします。

レルム追加ページが開きます。新規レルムを作成するので、レルム名に「demo」と入力して「作成」ボタンをクリックします。

レルムを作成すると、管理コンソールのメインページに遷移します。現在のレルムは「demo」となっているはずです。

左上隅のドロップダウン・メニューをクリックして、管理下にあるmasterレルムと今作成したレルムを切替えることができます。

1.2. クライアントの作成

次に、クライアントを作成します(※)。今回のケースにおいて、クライアントとは、OIDCで規定された「Relying Party」(OIDC 1.0のベースとなっているOAuth 2.0では「クライアント」とも言います)であり、Spring Bootアプリケーションのことになります。

※正確に言うと、クライアントのプロファイルを作成します。クライアント自体は、後述する「Spring Initializr」などを使って作成します。

左メニューバーで「クライアント」をクリックします。クライアントの一覧画面が表示されるので、「作成」ボタンをクリックします。

「sample-app」と入力して、「保存」ボタンをクリックします。

「有効なリダイレクトURI」に「http://localhost:8081/hello」と入力します。

1.3. ロールの作成

次に、ユーザーに割り当てるロールを作成します。このロールが割り当てられたユーザーだけが、Spring Bootアプリケーションにアクセスできるように、後で設定を行います。

ロールは、ユーザーの役割を意味し、ユーザーのタイプやカテゴリを識別するために利用します。管理者、ユーザー、マネージャー、従業員などが、組織内に存在する典型的なロールです。アプリケーションでは、ユーザーの管理が難しくならないように、個々のユーザーではなく特定のロールにアクセス権を割り当てることがよくあります。

左メニューバーで「ロール」をクリックします。ロールの一覧画面が表示されるので、「作成」ボタンをクリックします。

「ロール名」に「user」と入力して「保存」ボタンをクリックします。

1.4. ユーザーの作成とロールの割り当て

最後に、ユーザーを作成し、ロールを割り当てます。左メニューバーで「ユーザー」をクリックします。ユーザーの一覧画面が表示されるので、「作成」ボタンをクリックします。

ユーザー一覧のページが開きます。空のユーザーリストの右側にある「ユーザーの追加」をクリックします。

必須入力のユーザー名のみを入力して、「保存」ボタンをクリックすると、新規ユーザーの管理ページが開きます。

次に、新規ユーザーのパスワードを設定します。「クレデンシャル」タブをクリックします。

新しいパスワードとパスワード(確認)を入力すると、赤い「パスワードリセット」ボタンが表示されます。この時、「一時的」は「オフ」に変更して下さい。これにより、初回ログイン時にパスワードを変更する必要がなくなります。

「パスワードリセット」ボタンをクリックすると、パスワードがリセットされます。

最後に「ロールマッピング」のタグをクリックして、「使用可能なロール」の中にあるuserを「アサイン済みロール」に移動します。

以上でKeycloakの設定は完了です。

2.1. Spring Initializrでアプリの雛形作成

次に、Spring Bootアプリケーションを作成します。Spring Bootアプリケーションの雛形作成には、Spring Initializrを使用します。Spring Initializrのページにアクセスして下さい。

上の画面のように以下を入力、選択してから、「Generate Project」ボタンをクリックして下さい。

項目 設定値
Project Gradle ProjectまたはMaven Project
言語 Java
Dependencies Web、Thymeleaf、DevTools、Keycloak
Group com.example
Artifact sample-app

圧縮ファイルがダウンロードされるので、適当なディレクトリに解凍して下さい。

2.2. クラスとhtmlの作成

まずはトップページの静的なHTMLを作成します。src/main/resources/static/index.htmlというHTMLファイルを次のような内容で作成します。

<html>
<head>
    <title>Sample Application</title>
</head>
 <body>
   <h1>Sample Application</h1>
   <a href="/hello">Go to hello page!</a>
 </body>
</html>

次にこの画面から呼び出されるコントローラーと画面を作成します。コントローラーは、src/main/java/com/example/sampleapp/HelloController.javaというファイル名で次のような内容とします。

package com.example.sampleapp;

import java.util.Locale;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
class HelloController {

    @RequestMapping(value = "/hello")
    public ModelAndView hello(HttpSession ses, ModelAndView mav, Locale locale) {
        mav.setViewName("hello");
        mav.addObject("message", "Hello! Spring Boot and Keycloak!");
        return mav;
    }

    @RequestMapping(value = "/logout")
    public String logout(HttpServletRequest request) throws ServletException {
       request.logout();
       return "redirect:/";
    }
}

このコントローラから呼び出される画面は、src/main/resources/templates/hello.htmlというHTMLファイルで作成します。

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" th:with="lang=${#locale.language}" th:lang="${lang}">
<h1>Hello</h1>
<p th:text="${message}" /><br />
<p>
    <a href="/logout">Logout</a>
</p>
</html>

ディレクトリ構成は以下のようになっています。

これでサンプルのWebアプリケーションは完成しました。

2.3. アプリのKeycloak連携の設定

最後に、作成したWebアプリケーションにKeycloakと連携するための設定を行います。/src/main/resources/application.propertiesに以下の定義を追加して下さい。

keycloak.auth-server-url=http://localhost:8080/auth
keycloak.realm=demo
keycloak.public-client=true
keycloak.resource=sample-app
keycloak.security-constraints[0].authRoles[0]=user
keycloak.security-constraints[0].securityCollections[0].patterns[0]=/hello/
server.port=8081

http://localhost/hello/以下へのアクセスには認証が必要で、そのユーザーにはロール「user」が必要であることを定義しています。最後のプロパティは、このアプリケーションがポート8081でリッスンされることを指定しています。

以上で全ての設定は完了です。

動作確認

では、動作確認してみましょう。次のコマンドで作成したWebアプリケーションを起動します。

Gradleの場合

$ gradle bootRun

Mavenの場合

$ mvn spring-boot:run

http://localhost:8081にアクセスすると、次のような画面が表示されます。

「Go to hello page!」のリンクをクリックすると、Keycloakのログイン画面にリダイレクトされます。

作成したユーザーでログインして下さい。これまでの設定が適切にできていれば、次のような画面が表示されます。

最後に

このようにSpring BootベースのWebアプリケーションの認証をKeycloakに委譲するのはとても簡単です。簡単なだけでなく、標準的でセキュアなログイン処理を実装したことにもなります。

今回はSpring Boot Adapterを使用しましたが、Spring Security Adapterというものもあり、Spring Boot Keycloak Starterに含まれています。これについては、また別の機会に説明します(その機会があれば...)。


参考資料