Techioz Blog

Keycloak API 経由でユーザーを追加する場合、「realmRoles」パラメータは無視されます

概要

Keycloak API を介してユーザーを作成しようとしていますが、最初に追加されたときにレルムレベルのロールをユーザーに割り当てたいと考えています。ただし、ドキュメントに記載されているようには機能しないようです。

最初のユーザー作成 API リクエストの後に、単にユーザーへの 2 番目のロール追加 API リクエストを作成できることはわかっていますが、次のとおりです。

これを irb でテストするには、keycloak Ruby gem を使用して、まず Keycloak からアクセス トークンをリクエストします。

require 'keycloak'
json = Keycloak::Client.get_token_by_client_credentials
access_token = JSON.parse(json)['access_token']

以下のすべては Keycloak 内にユーザーを作成しますが、「所有者」ロールはありません。

Keycloak::Admin.generic_post('users', nil, { username: 'someone', realmRoles: ['owner'] }, access_token)
Keycloak::Admin.generic_post('users', nil, { username: 'someone', realmRoles: ['1fff5f5f-7357-4f73-b45d-65ccd01f3bc8'] }, access_token)
Keycloak::Admin.generic_post('users', nil, { username: 'someone', realmRoles: ['{"id":"1fff5f5f-7357-4f73-b45d-65ccd01f3bc8","name":"owner","description":"Indicates that a user is the owner of an organisation.","composite":false,"clientRole":false,"containerId":"MyRealmName"}'] }, access_token)

文字列の代わりにロール ハッシュを使用しようとすると、エラーが発生します。

Keycloak::Admin.generic_post('users', nil, { username: 'someone', realmRoles: [{"id"=>"1fff5f5f-7357-4f73-b45d-65ccd01f3bc8", "name"=>"owner", "description"=>"Indicates that a user is the owner of an organisation.", "composite"=>false, "clientRole"=>false, "containerId"=>"MyRealmName"}] }, access_token)

Traceback (most recent call last):
      16: from /home/thomas/.rvm/rubies/ruby-2.6.3/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
      15: from (irb):8
      14: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/keycloak-3.0.0/lib/keycloak.rb:541:in `generic_post'
      13: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/keycloak-3.0.0/lib/keycloak.rb:943:in `generic_request'
      12: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/keycloak-3.0.0/lib/keycloak.rb:915:in `block in generic_request'
      11: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/rest-client-2.0.2/lib/restclient.rb:71:in `post'
      10: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/rest-client-2.0.2/lib/restclient/request.rb:52:in `execute'
        9: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/rest-client-2.0.2/lib/restclient/request.rb:145:in `execute'
        8: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/rest-client-2.0.2/lib/restclient/request.rb:715:in `transmit'
        7: from /home/thomas/.rvm/rubies/ruby-2.6.3/lib/ruby/2.6.0/net/http.rb:920:in `start'
        6: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/rest-client-2.0.2/lib/restclient/request.rb:725:in `block in transmit'
        5: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/rest-client-2.0.2/lib/restclient/request.rb:807:in `process_result'
        4: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/keycloak-3.0.0/lib/keycloak.rb:916:in `block (2 levels) in generic_request'
        3: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/keycloak-3.0.0/lib/keycloak.rb:958:in `rescue_response'
        2: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/rest-client-2.0.2/lib/restclient/abstract_response.rb:103:in `return!'
        1: from /home/thomas/.rvm/gems/ruby-2.6.3/gems/rest-client-2.0.2/lib/restclient/abstract_response.rb:223:in `exception_with_response'
RestClient::InternalServerError (500 Internal Server Error)

Keycloak は以下を出力します。これは、予想どおり、ロールがハッシュではなく文字列の配列である必要があることを示しています。

08:53:27,889 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (default task-22) Uncaught server error: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
at [Source: (io.undertow.servlet.spec.ServletInputStreamImpl); line: 1, column: 37] (through reference chain: org.keycloak.representations.idm.UserRepresentation["realmRoles"]->java.util.ArrayList[0])

次のように、配列の代わりに単一の文字列を渡しても、同じことが起こります。

Keycloak::Admin.generic_post('users', nil, { username: 'someone', realmRoles: 'owner' }, access_token)

何か間違ったことをしているのでしょうか、それともこれは単に Keycloak API のバグなのでしょうか?

解決策

あなたは何も間違ったことはしていません。これは Keycloak API のバグです。

このリクエストは機能するはずです。

Keycloak::Admin.generic_post('users', nil, { username: 'someone', realmRoles: ['owner'] }, access_token)

残念ながら、ユーザー/グループを作成/更新しようとすると「realmRoles」属性が機能しないため、API ドキュメントは間違っています。

この動作に関する詳細情報は、Keycloak の公式バグ トラッカーで見つけることができます。

現時点での唯一の解決策は、RoleMappers を使用してロールをユーザーにマップし、API で複数のリクエストを行うことです。

これらの操作に関するドキュメント: https://www.keycloak.org/docs-api/18.0/rest-api/index.html#_role_mapper_resource