ELW株式会社 テックブログ

リアルなログをそのままお届けします。

QuarkusにおけるOIDCでのログインユーザー情報の保持方法

弊社ではバックエンドのフレームワークにQuarkusを採用し、Kotlinで使用しています。 表題通りQuarkusでログインユーザー情報を保持する方法が意外に公式に詳しく書かれていないので紹介させていただきます。

以下公式に、リクエストヘッダーから取得する方法は書いてあるので、これを参考にします。

https://quarkus.io/guides/security-customization#jaxrs-security-context

この例からわかるように、SecurityContextにセットするという方法も取ることができます。 ただ、Principalは文字列しか保持できないため、ログインユーザーの細かい情報を持ち回すのには不便です。 ですので以下のようなイメージで実装しました(一部改変しています)。

@Provider
@PreMatching
class SecurityOverrideFilter : ContainerRequestFilter {
    @Inject lateinit var userRepository: UserRepository
    @Inject lateinit var jwt: JsonWebToken
    @Inject lateinit var userIdentity: UserIdentity

    override fun filter(requestContext: ContainerRequestContext) {
        val email = jwt.getClaim<String?>("specific_claim") ?: return
        val user =
            userRepository.findByEmailOrNotFound(email).also {
                userIdentity.user = it
            }
        requestContext.securityContext =
            object : SecurityContext {
                override fun getUserPrincipal(): Principal = Principal { user.id.toString() }

                override fun isUserInRole(role: String?): Boolean = role?.let { it in accessTargetKindKeys } ?: false

                override fun isSecure(): Boolean = requestContext.securityContext.isSecure

                override fun getAuthenticationScheme() = requestContext.securityContext.authenticationScheme
            }
    }
}

@RequestScoped
class UserIdentity {
    var user: User = User()
}

jwtからメールアドレスを取得し、それを元にユーザーを取得し、RequestScopedのインスタンスに保持します。 これにより、CDIが使える箇所では UserIdentity を依存性注入することで自由にログインユーザー情報を取ることができます。