---
title: "Keycloak APIの使い方：Admin REST APIでユーザー作成とロール付与をcurlで行う手順"
url: "https://www.issoh.co.jp/tech/details/19378/"
published: 2026-11-05
updated: 2026-11-05
categories: ["セキュリティ"]
publisher: "株式会社一創"
---

# Keycloak APIの使い方：Admin REST APIでユーザー作成とロール付与をcurlで行う手順

Keycloakを自社の会員DBや人事システムとつなぐとき、管理コンソールの画面操作を自動化する入口になるのがAdmin REST APIです。本記事では、2026年11月5日時点の最新版Keycloak 26.8.1を前提に、サービスアカウントを持つクライアントの作り方、必要な管理ロールの選び方、`client_credentials`でのトークン取得、ユーザーの作成・検索・ロール付与・無効化までを、そのまま動かせるcurlのコマンド例で解説します。つまずきやすい401・403・409の切り分けと、APIで連携を自作すべきかの判断基準も扱います。

## まとめ：Keycloak APIはサービスアカウントのトークンで管理APIを呼ぶ

Keycloakの管理操作は、`/admin/realms/{realm}`配下のAdmin REST APIで呼べます。管理コンソールでできる操作はすべてAPIにもあり、2026年11月時点の公式OpenAPI定義には274のパスが載っています。

アプリから呼ぶなら、管理者のパスワードではなく、サービスアカウントを有効にしたクライアントのトークンを使います。ロールは対象レルムの`realm-management`から、必要なものだけを渡す設計です。ユーザーの作成・検索・更新は`manage-users`で足ります。ロールを名前で引く処理を入れるなら`view-realm`も要ります。

数百人規模までの会員同期や入退社の反映なら、APIを直接呼ぶ実装で十分に回ります。既存のLDAPやActive Directoryが正本なら、APIで同期を書くより[User Federationで読み込む構成](https://www.issoh.co.jp/tech/details/19236/)を先に検討してください。

## Keycloak APIの全体像：認証用OIDCとAdmin REST APIの役割分担

「Keycloak API」と呼ばれるものは、パスの先頭で2系統に分かれます。どちらを呼ぶのかを先に決めないと、トークンの取り方もロール設計も定まりません。製品そのものの機能や他製品との違いは[Keycloakとは？Oktaとの違いと連携手順](https://www.issoh.co.jp/tech/details/7663/)で扱っています。

### /realms配下のトークン発行と/admin/realms配下の管理操作の違い

`/realms/{realm}/protocol/openid-connect/`配下は、ログインやトークン発行を担う標準のエンドポイントに当たります。アプリの利用者が認証するときに使い、仕様は[OAuth 2.0](https://www.issoh.co.jp/tech/details/8369/)とOpenID Connectに従います。

`/admin/realms/{realm}/`配下はKeycloak独自の管理APIです。[公式のServer Developer Guide](https://www.keycloak.org/docs/latest/server%5Fdevelopment/index.html#admin-rest-api)は、管理コンソールが持つ機能をすべて備えると説明しています。ユーザーやロールを登録・変更するのはこちらで、呼ぶには管理ロールを持つアクセストークンが要ります。

| 系統             | パスの例            | 主な用途               | 必要な権限                |
| -------------- | --------------- | ------------------ | -------------------- |
| OIDCエンドポイント    | myappのトークン発行用パス | ログイン・トークン発行        | クライアントの資格情報          |
| Admin REST API | myappのユーザー管理用パス | ユーザー・ロール・クライアントの管理 | realm-managementのロール |

表のパス例は、OIDC側が`/realms/myapp/protocol/openid-connect/token`、管理API側が`/admin/realms/myapp/users`です。本記事が扱うのは後者です。トークンは前者で取り、後者にBearerとして渡す、という順に動きます。

### 公式リファレンス26.8.1で確認できるエンドポイントの探し方

エンドポイントの正本は[Keycloak Admin REST APIのリファレンス](https://www.keycloak.org/docs-api/latest/rest-api/index.html)です。同じ場所に`openapi.json`があり、2026年11月5日に取得した定義には274のパスがありました。リファレンスのHTMLは長いので、OpenAPI定義を`jq`で引くほうが速く探せます。

読むときの注意が2つあります。パスの`{client-id}`はクライアントの内部ID（UUID）で、画面で入力する`clientId`ではありません。ロール関連の`{role-name}`は名前で、IDではありません。リファレンスにも「not clientId!」「not id!」と明記されており、取り違えると404になります。

## 管理APIを呼ぶトークンの取得：admin-cliとサービスアカウントの使い分け

トークンの取り方は、手元で試す場合とアプリに組み込む場合で分けます。結論から言うと、アプリには管理者のパスワードを持たせず、レルムごとのサービスアカウントを使います。

### admin-cliとパスワードグラントで試す方法と有効期限1分の制約

公式ガイドの最初の例は、`master`レルムの管理者で`admin-cli`クライアントからパスワードグラントでトークンを取る方法です。ガイドには、このトークンは既定で1分で切れると書かれています。

動作確認には手軽です。ただし管理者のパスワードをスクリプトに書くことになり、そのトークンは全レルムを操作できます。バッチや本番のアプリに持ち込む方法ではありません。手元で数回叩いて挙動を見る用途に限ってください。

### サービスアカウントを有効にしたクライアントをmyappレルムに作る設定

アプリ用には、管理したいレルム（以下`myapp`）にAPI専用のクライアントを作ります。[管理ガイドのUsing a service account](https://www.keycloak.org/docs/latest/server%5Fadmin/index.html#%5Fservice%5Faccounts)に沿った手順は次のとおりです。

1. 管理コンソールで`myapp`レルムを選び、Clientsから`user-sync`という名前のOpenID Connectクライアントを作る
2. SettingsでClient authenticationをOnにし、Service account rolesにチェックを入れる。Standard flowはオフにする
3. CredentialsタブでClient Secretを控える
4. Client scopesタブで専用スコープ（`user-sync-dedicated`）を開き、Scopeタブで必要なロールのスコープを割り当てる
5. Service account rolesタブで、`realm-management`の必要なロールを割り当てる

手順4と5は両方必要です。トークンに入るロールは、スコープの割り当てとサービスアカウントのロールの交差になるからです。26.8系の管理ガイドは「Full Scope Allowed」を非推奨とし、オンにせず必要なスコープを明示するよう求めています。

### manage-usersとview-realmに絞るユーザー連携用のロール設計

各レルムには`realm-management`という組み込みクライアントがあり、管理権限はそのクライアントロールで表されます。[管理ガイドのDedicated realm admin consoles](https://www.keycloak.org/docs/latest/server%5Fadmin/index.html#%5Fper%5Frealm%5Fadmin%5Fpermissions)には、`manage-users`や`view-realm`、全権を束ねた`realm-admin`を含む22個が並びます。

ユーザー連携に要るのは2つです。`manage-users`があればユーザーの作成・検索・更新・削除が通ります。ソースの`UserPermissions`は、`manage-users`か`view-users`を持てば閲覧可、閲覧できれば検索も可と判定しています。

見落としやすいのはロールの参照です。`GET /roles/{role-name}`は、[26.8.1のRealmPermissions](https://github.com/keycloak/keycloak/blob/26.8.1/services/src/main/java/org/keycloak/services/resources/admin/fgap/RealmPermissions.java)で`view-realm`か`manage-realm`を要求します。`manage-users`だけでは403になるため、`view-realm`の追加が必要です。`realm-admin`を丸ごと渡すと、漏れたときにレルム設定まで書き換えられます。

### client\_credentialsでアクセストークンを取得するcurlコマンド

トークンは`myapp`レルムのトークンエンドポイントへ`grant_type=client_credentials`で取りに行きます。管理ガイドのとおり、資格情報はBasic認証のヘッダで送れます。以降の例は`jq`がある前提です。

```
KC=http://localhost:8080
REALM=myapp
CLIENT_ID=user-sync
CLIENT_SECRET='CredentialsタブのClient Secret'

TOKEN=$(curl -s -u "${CLIENT_ID}:${CLIENT_SECRET}" \
  -d grant_type=client_credentials \
  "${KC}/realms/${REALM}/protocol/openid-connect/token" | jq -r .access_token)

echo "${TOKEN}" | cut -c1-20
```

応答の`expires_in`が有効秒数です。この有効秒数を決める設定は、レルムのAccess Token Lifespanです。このグラントではリフレッシュトークンが既定で発行されないため、切れたら同じ要求で取り直します。トークンの中身は[JWTの構造](https://www.issoh.co.jp/tech/details/13453/)どおりで、`resource_access.realm-management.roles`に割り当てたロールが入っているかで設定を確かめられます。

## Admin REST APIでのユーザー操作：作成・検索・ロール付与・無効化のcurl例

ここからは取得した`TOKEN`を使い、入社から退職までの一連の操作を順に呼びます。`myapp`レルムに`app-user`というレルムロールがある前提です。

### POST /usersで初期パスワード付きのユーザーを作成する手順

ユーザーの作成は`POST /admin/realms/{realm}/users`です。`credentials`に`temporary: true`のパスワードを入れると、初回ログインで変更を求められます。メールアドレスは環境変数`NEW_USER_EMAIL`に入れてから実行してください。

```
BODY=$(jq -n --arg email "${NEW_USER_EMAIL}" '{
  username: "taro.yamada",
  email: $email,
  firstName: "Taro",
  lastName: "Yamada",
  enabled: true,
  emailVerified: false,
  credentials: [{type: "password", value: "Temp-Pass-2026", temporary: true}]
}')

curl -s -i -X POST "${KC}/admin/realms/${REALM}/users" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d "${BODY}" | grep -i -E '^(HTTP|location)'
```

成功すると201が返り、本文は空です。作成したユーザーのIDは`Location`ヘッダの末尾に入ります。[26.8.1のUsersResource](https://github.com/keycloak/keycloak/blob/26.8.1/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java)は、作成後に`Response.created`でユーザーIDつきのURLを返しています。

### usernameとexact=trueで1件に絞る検索と既定100件のページング

IDが分からないときは検索で引きます。`username`は既定で部分一致なので、`exact=true`を付けないと`taro`で`taro.yamada`も`taro2`も返ります。

```
USER_ID=$(curl -s -H "Authorization: Bearer ${TOKEN}" \
  "${KC}/admin/realms/${REALM}/users?username=taro.yamada&exact=true" | jq -r '.[0].id')

curl -s -H "Authorization: Bearer ${TOKEN}" "${KC}/admin/realms/${REALM}/users/count"

curl -s -H "Authorization: Bearer ${TOKEN}" \
  "${KC}/admin/realms/${REALM}/users?first=100&max=100&briefRepresentation=true"
```

一覧の`max`は省略すると100件です。全件を同期するなら、`count`で総数を取り、`first`を100ずつ進めて回します。`briefRepresentation=true`にすると属性を省いた軽い応答になり、件数の多いレルムで転送量を抑えられます。

### レルムロールの割り当てとSMTP設定を使うパスワード再設定メールの送信

ロールの割り当ては、ロールの表現をそのまま配列に入れて`role-mappings/realm`へPOSTします。メール送信の`execute-actions-email`は、レルムにSMTPの設定が無いと送れません。

```
ROLE=$(curl -s -H "Authorization: Bearer ${TOKEN}" \
  "${KC}/admin/realms/${REALM}/roles/app-user")

curl -s -o /dev/null -w "%{http_code}\n" -X POST \
  "${KC}/admin/realms/${REALM}/users/${USER_ID}/role-mappings/realm" \
  -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
  -d "[${ROLE}]"

curl -s -o /dev/null -w "%{http_code}\n" -X PUT \
  "${KC}/admin/realms/${REALM}/users/${USER_ID}/execute-actions-email?lifespan=86400" \
  -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
  -d '["UPDATE_PASSWORD","VERIFY_EMAIL"]'
```

どちらも成功時は204です。`lifespan`はメール内リンクの有効秒数で、例では24時間にしています。初期パスワードを渡さずにメールで本人に設定させる運用なら、作成時の`credentials`を省いてこのメールだけを送る形にできます。

### 退職者の無効化はGETした表現を書き換えてPUTしセッションも切る

退職者は削除より無効化が安全です。監査ログと紐付いたユーザーIDが残るからです。`PUT /users/{id}`には、一度GETした表現の`enabled`だけを`false`に変えて送り返します。

```
curl -s -H "Authorization: Bearer ${TOKEN}" "${KC}/admin/realms/${REALM}/users/${USER_ID}" \
  | jq '.enabled = false' > user.json

curl -s -o /dev/null -w "%{http_code}\n" -X PUT \
  "${KC}/admin/realms/${REALM}/users/${USER_ID}" \
  -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -d @user.json

curl -s -o /dev/null -w "%{http_code}\n" -X POST \
  "${KC}/admin/realms/${REALM}/users/${USER_ID}/logout" \
  -H "Authorization: Bearer ${TOKEN}"
```

GETした表現を戻す形にしておけば、ほかの属性を意図せず書き換える心配がありません。最後の`logout`は、そのユーザーの全セッションを消します。ただし発行済みのアクセストークンを署名の検証だけで受け入れるAPIでは、そのトークンは期限まで通ります。寿命を短く保つのはこのためです。

## Node.jsから呼ぶ場合：keycloak-admin-clientで同じ処理を書く方法

アプリの中で呼ぶなら、curlを組み立てるより公式のクライアントライブラリが楽です。npmの`@keycloak/keycloak-admin-client`はサーバーと同じ26.8.1が最新です。

### client\_credentialsで認証し58秒ごとに取り直す公式READMEの書き方

[公式README](https://github.com/keycloak/keycloak/blob/26.8.1/js/libs/keycloak-admin-client/README.md)は、リフレッシュトークンが無い`client_credentials`では`auth`を58秒ごとに呼び直す例を載せています。同じ考え方で、ユーザー作成とロール付与を書くと次のようになります。

```
import KcAdminClient from '@keycloak/keycloak-admin-client';

const kc = new KcAdminClient({ baseUrl: 'http://localhost:8080', realmName: 'myapp' });
const credentials = {
  grantType: 'client_credentials',
  clientId: 'user-sync',
  clientSecret: process.env.KC_CLIENT_SECRET,
};
await kc.auth(credentials);
setInterval(() => kc.auth(credentials), 58 * 1000);

const { id } = await kc.users.create({
  username: 'taro.yamada',
  email: process.env.NEW_USER_EMAIL,
  enabled: true,
});
const role = await kc.roles.findOneByName({ name: 'app-user' });
await kc.users.addRealmRoleMappings({ id, roles: [{ id: role.id, name: role.name }] });
```

呼んでいるのは前章と同じエンドポイントなので、必要なロールも変わりません。トークンの寿命を5分以上に延ばしているレルムでも、58秒の間隔はそのままで害はありません。

## Keycloak APIで詰まりやすいエラーと応答コードごとの切り分け

Admin REST APIのエラーは、本文が短いか空のことが多く、応答コードから原因を絞るのが早道です。

### 401・403・404・409の4つで原因を切り分ける確認順

| コード | よくある原因                   | 確認すること                    |
| --- | ------------------------ | ------------------------- |
| 401 | トークン切れ・別レルムのトークン         | expires\_inとトークンのissのレルム名 |
| 403 | 管理ロール不足                  | トークン内の管理ロール               |
| 404 | clientIdと内部IDの取り違え       | パスに入れたのがUUIDか             |
| 409 | 同じusernameかemailのユーザーが既存 | exact=trueで検索して既存IDを使う    |

表の403では、トークンの`resource_access`に`manage-users`などの管理ロールがあるかを確認してください。403で最初に疑うのは、サービスアカウントにロールを付けたのにスコープ側へ割り当てていないケースです。トークンをデコードして`realm-management`のロールが空なら、前述の手順4が抜けています。409は作成処理を再実行したときに出やすいので、同期バッチは「検索して無ければ作成」の順に組みます。

## Admin REST APIで連携を自作する判断：採用する条件と見送る場面

APIで何でも書けるぶん、作らなくてよい連携まで自作しがちです。採用と見送りの線を条件で示します。

### 会員DBや人事データとの同期をAPIで組むべき条件とSCIM・LDAPとの使い分け

APIでの自作が合うのは、自社サービスの会員登録画面からKeycloakにユーザーを作る場合と、正本がCSVや独自DBで標準プロトコルを話せない場合です。入社・異動・退職を夜間バッチで反映する程度なら、本記事の4つのAPIで足ります。

見送るべきなのは、正本がLDAPやActive Directoryの場合です。User Federationで読み込めば同期のコードは要りません。SaaS側がSCIMを話すなら、[SCIMでのプロビジョニング](https://www.issoh.co.jp/tech/details/15876/)に寄せたほうが保守の手間が減ります。26.8系の管理ガイドにはSCIM APIがAdmin REST APIと同じ権限モデルで動くとの記載もあります。

### masterレルムの管理者資格情報をアプリに持たせる構成を避ける理由

公式ガイドの最初の例どおり、`master`の`admin`でトークンを取るコードを本番に残す構成は採用しません。そのトークンは全レルムの全設定を変えられ、漏えい時の被害がKeycloak全体に及ぶからです。管理ガイドも`master`はレルムの作成と管理だけに使うよう書いています。

レルムごとにサービスアカウントを分け、ロールを`manage-users`と`view-realm`に絞れば、漏れても影響はそのレルムのユーザー管理に留まります。Client Secretは定期的に再生成し、Keycloak自体も[修正版へ更新する手順](https://www.issoh.co.jp/tech/details/19094/)と合わせて運用してください。権限設計からID連携の実装までまとめて任せたい場合は、一創の[認証基盤・ID管理システム開発](https://www.issoh.co.jp/service/system/identity/)で、既存システムとの同期方式の選定から相談を受けています。

## よくある質問

Keycloak APIを使い始める開発者からよく出る質問に、26.8.1時点の仕様で答えます。

### Keycloak APIのドキュメントはどこにありますか？

エンドポイントの一覧はkeycloak.orgの「Keycloak Admin REST API」リファレンスにあり、同じ場所のopenapi.jsonで機械的に読めます。トークンの取り方はServer Developer Guide、管理ロールの意味はServer Administration Guideという分担です。版ごとにURLの`latest`を`26.8.1`のような版番号に替えると、その版の内容に固定できます。

### admin-cliで取ったトークンがすぐ使えなくなるのはなぜですか？

`master`レルムのトークン寿命が短く設定されているためで、公式ガイドも既定で1分と書いています。スクリプトの途中で401が出たら、トークンを取り直してください。寿命を延ばすより、本記事のようにレルムごとのサービスアカウントへ切り替えるほうが、権限も絞れて安全です。

### Keycloak APIでユーザーのパスワードを直接設定できますか？

ユーザーのパスワードを直接設定することは可能です。`PUT /admin/realms/{realm}/users/{id}/reset-password`に`type`・`value`・`temporary`を持つJSONを送ると、204で設定されます。レルムのパスワードポリシーに合わない値を送った場合の応答は400です。本人に決めさせたい場合は、`execute-actions-email`で`UPDATE_PASSWORD`を送る方法を選びます。

### グループへの追加もAPIでできますか？

できます。`PUT /admin/realms/{realm}/users/{id}/groups/{groupId}`で、本文なしの呼び出しで所属させられます。`groupId`はグループ名ではなく内部IDです。ロールをグループに持たせて所属で権限を配る設計は、[Keycloakの権限モデル](https://www.issoh.co.jp/tech/details/3293/)で扱っています。

### Docker上のKeycloakでも同じURLで呼べますか？

呼べます。パスは同じで、先頭のホスト名とポートが変わるだけです。リバースプロキシの後ろに置く場合は、`/admin/`を外部に公開しない構成が多いため、同期バッチは内部ネットワークから呼びます。公開パスの絞り方は[Keycloak Dockerの本番構成](https://www.issoh.co.jp/tech/details/19368/)で解説しています。

## 関連記事

- [Keycloakとは？Oktaとの違いと連携手順｜Auth0・Cognito比較で導入を判断【2026年10月】](https://www.issoh.co.jp/tech/details/7663/)：Keycloakの機能と他製品との違いを確認できます。
- [Keycloakのデータベース設定と使い方｜PostgreSQL接続・対応DB・バックアップから権限モデルまで](https://www.issoh.co.jp/tech/details/3293/)：起動・DB設定とロール・グループの設計を扱っています。
- [Keycloak Dockerの本番構成：Composeでの起動とリバースプロキシ・ヘルスチェックの設定](https://www.issoh.co.jp/tech/details/19368/)：APIを呼ぶ先のKeycloakを本番構成で立てる手順です。
- [OAuthとは？OAuth 2.0の仕組み・認可フローと認証との違い、OAuth 2.1の変更点をわかりやすく解説](https://www.issoh.co.jp/tech/details/8369/)：client\_credentialsを含む認可フローの前提知識です。
- [認証・ID管理とは？MFA・SSO・OIDC・IDaaSの違いと選定を解説【2026年版】](https://www.issoh.co.jp/column/details/13631/)：自前のKeycloakとIDaaSを比べる際の全体像です。

---

出典: [Keycloak APIの使い方：Admin REST APIでユーザー作成とロール付与をcurlで行う手順](<https://www.issoh.co.jp/tech/details/19378/>)（株式会社一創）
