LoginSignup
1
1

More than 1 year has passed since last update.

Keycloakで認証したユーザー名を大文字にする

Last updated at Posted at 2022-08-28

はじめに

Spring Boot ベースのWebアプリケーションで、Keycloakを標準のまま(ユーザーストレージなどのカスタマイズなし)利用していると、大文字のユーザー名でも、小文字で保存されてしまう問題に直面しました。他の方の記事にもあるように、これが標準の動きっぽい。
システムのユーザー名は大文字英数字で構成されており、トークンの「preferred_username」クレームの値を画面表示などに利用しているため、回避策を調べました。

実行環境

  • keycloak 12.0.4
  • Java11
  • Spring Security 5.4.5
  • Spring Boot 2.4.3

回避策

Spring Security のカスタマイズ箇所を利用し、ユーザ名を大文字に変換するOidcUserServiceのサブクラスを用意しました。

OidcUserServiceのサブクラス
package demo.keycloak;

import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Component;

@Component
public class UpperCaseOidcUserService extends OidcUserService {

	@Override
	public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
		OidcUser originalUser = super.loadUser(userRequest);
		System.out.println("[UpperCaseOidcUserService] originalUser=" + originalUser.getPreferredUsername());
		OidcUser upperCaselUser = new UpperCaseOidcUser(originalUser);
		System.out.println("[UpperCaseOidcUserService] upperCaselUser=" + upperCaselUser.getPreferredUsername());
		return upperCaselUser;
	}

	/**
	 * preferred_usernameを大文字にするUserクラス
	 */
	public static class UpperCaseOidcUser extends DefaultOidcUser {
		public UpperCaseOidcUser(OidcUser originalUser) {
			super(originalUser.getAuthorities(), originalUser.getIdToken(), originalUser.getUserInfo());
		}

		@Override
		public String getPreferredUsername() {
			return super.getPreferredUsername().toUpperCase();
		}
	}
}
ユーザ名を表示するController
package demo.keycloak;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.RequiredArgsConstructor;

@Controller
@RequestMapping("top")
@RequiredArgsConstructor
public class TopController {

	@GetMapping
	public String top(Model model) {
		var principal = (OidcUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		System.out.println("[TopController] user=" + principal.getPreferredUsername());

		return "top";
	}
}

検証結果

ログイン画面(ユーザー名=user1)
login.png

コンソール
[UpperCaseOidcUserService] originalUser=user1
[UpperCaseOidcUserService] upperCaselUser=USER1
[TopController] user=USER1

Keycloakが内部で保存する値は小文字のままですが、アプリーケーションに返却する値はこれで大文字になりました。他にも、Keycloak側の設定で回避する術もあるみたいですが、そこは検証できたら追記したい。

参考記事

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1