はじめに
ここでは、Keycloakをインストール・設定し、Spring Bootアプリケーションから接続することを試してみます。
メモ書きなので説明は必要最小限です(暇なときに説明を書くかも)
環境
使用した環境とバージョンは以下のとおりです。
- CentOS 7.5(Keycloak)
- Keycloak 10.0.2
- Spring Boot 2.3.1
作成するSpring BootアプリケーションはローカルのWindows上で開発・実行します。
Keycloakインストール
Keycloakのインストールの前に、まずOpenJDK(1.8)をインストールします。
# yum install java
次のKeycloakのインストールですが、下のURLからモジュール(zip)をダウンロードし、サーバへ展開するだけです。
今回ダウンロードしたのは「keycloak-10.0.2.zip」です。
# unzip keycloak-10.0.2.zip
Keycloakの起動と設定
Keycloakを起動する前に管理者アカウント(admin)を作成します。
# cd keycloak-10.0.2
# ./bin/add-user-keycloak.sh -u admin
Press ctrl-d (Unix) or ctrl-z (Windows) to exit
Password:
Added 'admin' to '/opt/keycloak-10.0.2/standalone/configuration/keycloak-add-user.json', restart server to load user
次にKeycloakを起動します。ローカル以外からもアクセスできるように「-b 0.0.0.0」をつけて起動しています。
# ./bin/standalone.sh -b 0.0.0.0
~省略~
00:35:51,363 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management
00:35:51,363 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990
00:35:51,363 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: Keycloak 10.0.2 (WildFly Core 11.1.1.Final) started in 22714ms - Started 591 of 889 services (606 services are lazy, passive or on-demand)
起動後、以下のURLをブラウザから開きます。
- http://[ホスト名]:8080/auth/
ブラウザでは以下の画面が開きます。
[Administration Console]をクリックするとログイン画面へ遷移します。
作成していた管理者アカウント(admin)でログインします。
ログイン後、最初にレルム(realm)を作成します。
ここでは"test realm"としています。
外部アプリ用のクライアントを作成します。
[Clients]タブを選択し、[Create]をクリックします。
Client IDを入力します。ここでは"login-app"としています。
作成完了後、作成したClientを一覧から選択し、"Valid Redirect URIs"を"http://localhost:8081/*"に変更しています。これが今回作成するSpring BootアプリケーションのURIとなります。
ロール作成
次にロールを作成するために[Roles]タブを選択し、[Add Role]をクリックします。
ロール名(user)を入力し、[Save]をクリックします。
ユーザ作成
ユーザを作成するために[Users]タブを選択し、[Add user]をクリックします。
Usernameに[user1]を入力し、[Save]をクリックします。
[Credentials]タブを選択し、パスワードを入力します。
ロールとユーザの紐づけ
作成したユーザ(user1)をロール(user)に紐づけるため、[Role Mappings]タブを選択し、user1を[Available Roles]から[Assigned Roles]へ移動します。
Spring BootでKeycloakを使用
Keycloakクライアントアダプターを使用してSpring Bootに接続します。
pom.xml
以下のpom.xmlを持つMavenプロジェクトを作成します。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>spring-boot-keycloak</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<properties>
<keycloak-adapter-bom.version>10.0.2</keycloak-adapter-bom.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>${keycloak-adapter-bom.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.5.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
メインアプリ
今回のメインとなるアプリケーションクラスです。
普通のSpring Bootのアプリケーションです。
@SpringBootApplication
public class App {
public static void main(String... args) {
SpringApplication.run(App.class, args);
}
}
コントローラとHTMLファイルの作成
Controller(コントローラ)クラスを以下のように作成。
"/" -> index.html, "hello" -> hello.htmlを読み込むようにしています。
@Controller
public class WebController {
@GetMapping(path = "/")
public String index() {
return "index";
}
@GetMapping(path = "/hello")
public String customers(Principal principal, Model model) {
model.addAttribute("username", principal.getName());
return "hello";
}
}
index.htmlとhello.htmlはJavaテンプレートエンジンであるThymeleafを使用しています。
index.htmlにアクセスするとログインリンクが出て、リンクをクリックするとKeyCloakによるログインの後、hello.htmlに遷移するようにしています。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
<div class="container">
<div>
<h1>Portal</h1>
</div>
<div>
<a th:href="@{/hello}">Login</a>
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
<div id="container">
<h1>
Hello, <span th:text="${username}"></span>
</h1>
</div>
</body>
</html>
Keycloakとアプリケーションの設定
application.propertiesは以下のように設定しています。
# server port
server.port=8081
# Keycloak
keycloak.auth-server-url=http://[Keycloakサーバのホスト名]:8080/auth
# レルム名を設定する。
keycloak.realm=test realm
# クライアントIDを設定する。
keycloak.resource=login-app
keycloak.public-client=true
## OpenID ConnectのIDトークン属性を設定。
keycloak.principal-attribute=preferred_username
Keycloakクライアントアダプター
Keycloakクライアントアダプター(keycloak-spring-security-adapter)を使用して、アクセス制御する設定を行います。
@KeycloakConfiguration
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider provider = keycloakAuthenticationProvider();
provider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(provider);
}
// Spring Security AdapterとSpring Boot Adapterを一緒に使用する場合、application.propertiesから
// 設定情報を取得するために必要。
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/hello*")
.hasRole("user")
.anyRequest().permitAll();
}
}
ポイントは以下の箇所で、"/hello*"にマッチした場合、"user"ロールを持っている場合のみ認可するようにしています。
http.authorizeRequests()
.antMatchers("/hello*")
.hasRole("user")
.anyRequest().permitAll();
プログラム作成は以上で完了です。
作成したSpring Bootアプリケーションの起動
作成したSpring Bootアプリケーションの起動するために以下のコマンドを実行します。
mvn clean spring-boot:run
起動後、以下のURLでSpring Bootアプリケーションへアクセスします。
アクセスすると、以下のログインリンクがある画面が表示されます。
ここでリンクをクリックすると、「/hello」とマッチしてKeycloakでの認証にうつります。ログイン画面ではKeycloakの管理コンソールで作成した、"user"ロールを持つ"user1"でログインします。
初めてのログインの場合は以下のようにパスワードの変更が表示されます。
ログインに成功すると、以下のようにユーザ名を表示するだけの画面へ遷移するようになっています。