ログイン中のユーザー情報を使う
Keelson がログインと、アプリを開ける人の確認を行います。アプリでは、そのユーザー情報を使って、作成者を記録したり、本人のデータだけを表示したりできます。
「誰がどの申請を承認できるか」など、アプリ内の業務ルールはアプリ側で実装します。用途に応じて、次の 3 つの方法を使い分けます。
| やりたいこと | 使うもの | 追加設定 |
|---|---|---|
| 誰がアクセスしているか知りたい(作成者の記録、自分のデータだけ表示) | X-Keelson-User-Id などのユーザー情報ヘッダー | 不要 |
| アプリの運用者(デプロイ・設定変更ができる人)だけに見せる画面を作りたい | ヘッダー X-Keelson-User-App-Perms | 不要(権限はコンソールで設定) |
| 部署ごと・役職ごとの分岐、承認者の判定 | Identity SDK の attributes.groups | keelson apps directory enable |
「上司だけが承認できる」のような業務上の権限は、アプリ管理用の manage ではなく、所属グループ、またはアプリ自身のデータ(担当者テーブルなど)で判断します。manage を持つのはアプリをデプロイ・設定できる人であり、業務上の承認者と一致するとは限りません。
1. 誰がアクセスしているか
Section titled “1. 誰がアクセスしているか”Keelson は、ログイン済みユーザーからのリクエストに、ユーザー情報をヘッダー(リクエストに付く付加情報)として渡します。アプリのサーバー側で読み取れます。
| ヘッダー | 内容 |
|---|---|
X-Keelson-User-Id | ユーザー ID(安定した識別子。DB に保存するならこれ) |
X-Keelson-User-Email | メールアドレス(Keelson に値がなければ空文字) |
X-Keelson-User-Name | 表示名(Keelson に値がなければ空文字) |
作成者を記録するなら、データの保存時にユーザー ID も記録します。本人のデータだけを表示するなら、DB の検索条件にその ID を使います。ヘッダーを読み取るだけで、データの絞り込みが自動で行われるわけではありません。
# FastAPI / Flaskuser_id = request.headers.get("X-Keelson-User-Id")email = request.headers.get("X-Keelson-User-Email")// Expressconst userId = req.headers["x-keelson-user-id"];const email = req.headers["x-keelson-user-email"];これらのユーザー情報は、Keelson がログインを確認したうえで付けます。呼び出し元が同名のヘッダーを送っても、Keelson が確認したユーザー情報に置き換えられます。アプリ側で Keelson のログインセッションを管理する必要はありません。
SDK で読み取る
Section titled “SDK で読み取る”Identity SDK を使うと、ユーザー情報を id、email、name としてまとめて取得できます。導入方法は Keelson SDK のインストールを参照してください。以下の例はサーバー側で実行します。
getCurrentUser はヘッダーを読むだけで、外部への通信や Directory API の有効化は不要です。JavaScript では await を付けて呼びます。ユーザー ID のヘッダーがない場合や空の場合は例外(IdentityError)になります。
import { getCurrentUser } from "@keelsonhq/identity";
app.get("/", async (req, res) => { const user = await getCurrentUser({ headers: req.headers }); // { id, email, name } res.type("text").send(`こんにちは、${user.name ?? "ゲスト"} さん`);});このアプリでの権限(X-Keelson-User-App-Perms)もまとめて取得するなら getRequestUser(Python は get_request_user、Go は GetRequestUser)を使います。戻り値は getCurrentUser の値に perms を足したものです(使い方)。
2. 運用者だけの画面
Section titled “2. 運用者だけの画面”アプリの権限は「閲覧(view)」と「管理(manage)」の 2 種類で、コンソールまたは CLI でグループに割り当てます(グループとアプリ権限)。manage はデプロイ・設定変更・シークレット編集ができる運用者の権限で、既定では Owner / Admin / Developer が持ちます。Keelson はその結果をヘッダーで渡します。
X-Keelson-User-App-Perms | 意味 |
|---|---|
view | 閲覧できる |
view,manage | 閲覧と管理ができる |
アプリは manage が含まれるかだけを見ます。グループ名はコードに書きません。
// Express — ヘッダーはリクエストごとに違うので、ハンドラの中で読むfunction canManage(req) { const perms = (req.headers["x-keelson-user-app-perms"] ?? "").split(","); return perms.includes("manage");}
app.get("/admin", (req, res) => { if (!canManage(req)) return res.status(403).end(); res.send("運用者向けの画面");});# FastAPI / Flask — 同じくリクエストごとに読むdef can_manage(request) -> bool: perms = request.headers.get("X-Keelson-User-App-Perms", "").split(",") return "manage" in perms「経理チームだけが使えるアプリ」は権限の割り当てだけで実現でき、アプリ側のコードは要りません(チームにアプリを共有する)。「運用者だけが設定画面を開ける」は manage の確認で実現できます。誰が manage を持つかは、コードを変えずにコンソールで変えられます。
3. グループごとの分岐
Section titled “3. グループごとの分岐”部署ごと・役職ごとの分岐や、「承認者だけが承認できる」のような業務上の権限が必要なら、Identity SDK でユーザーの所属グループを取得します。
画面の出し分けだけでは不十分です。「本人の申請だけ見える」を実装するときは、一覧の絞り込みに加えて、API で他人の申請 ID を指定しても取得・更新できないことをサーバー側で確認してください。判定に使うのは、ブラウザから送られた値ではなく、Keelson が付けたヘッダーや SDK の戻り値です。
グループやメンバーの情報を取得するには、Directory API の読み取りを許可し、再デプロイします。有効にしただけでは、実行中のアプリはまだ利用できません。
keelson apps directory enablekeelson deploy再デプロイすると、環境変数 KEELSON_DIRECTORY_TOKEN がアプリに渡され、SDK が自動で使います。トークンはサーバー側だけで使い、ブラウザに渡さないでください。
import { getCurrentIdentity } from "@keelsonhq/identity";
// リクエストを処理する関数の中で取得します。const me = await getCurrentIdentity({ headers: req.headers });const groups = me.attributes?.groups ?? []; // 例: ["everyone", "developers", "経理"]const isAccountingMember = groups.includes("経理");// この結果を使って、経理向けの操作を許可するか判断します。from keelson import identity
me = identity.get_current_identity(headers=request.headers)groups = (me.attributes.groups or []) if me.attributes else []is_accounting_member = "経理" in groups# この結果を使って、経理向けの操作を許可するか判断します。attributes.groups に入るのはグループのキーです。
- ロールに応じたシステムグループ: Owner は
ownersdeveloperseveryone、Admin はadminsdeveloperseveryone、Developer はdeveloperseveryone、App User はeveryone - そのアプリに権限が割り当てられているカスタムグループのうち、ユーザーが属するもの。アプリに割り当てていないグループは出ません
- キーは変わらないので、コードに書いて判定に使えます。日本語のキー(
経理)も使えます
getCurrentIdentity は Directory API に問い合わせます。戻り値には、ユーザー(user.id、user.email、user.name)、ワークスペースでのロール(workspace.role)、このアプリでの権限(app.permissions)も含まれます。getCurrentUser とはユーザー情報の参照方法が異なります。
担当者の選択肢にメンバー一覧を使う
Section titled “担当者の選択肢にメンバー一覧を使う”担当者の選択肢を出すなど、他のメンバーの情報が必要なときは listMembers / list_members(検索、ロール・グループで絞り込み)、getUser、listGroups が使えます。
メンバーごとに id、email、name、role、image_url が返ります。image_url はプロフィール画像の URL(img.clerk.com から配信)で、画像が無いメンバーは null です。URL に width / height のクエリを付けると、縮小した画像を取得できます。
サーバー側では、選択肢に必要な項目だけを返します。
import { listMembers } from "@keelsonhq/identity";
// リクエストを処理する関数の中で取得します。1 回で最大 100 人です。const page = await listMembers({ group_key: "developers", limit: 100 });const options = page.items.map((m) => ({ id: m.id, label: m.name || m.email, image_url: m.image_url, // 文字列または null}));from keelson import identity
page = identity.list_members(group_key="developers", limit=100)options = [ {"id": m.id, "label": m.name or m.email, "image_url": m.image_url} for m in page.items]ブラウザ側では、画像が無いときや読み込みに失敗したときに頭文字を表示します。
function avatar(option) { const initials = document.createElement("span"); initials.className = "avatar-initials"; initials.textContent = option.label.slice(0, 1).toUpperCase(); if (!option.image_url) return initials;
const img = document.createElement("img"); img.className = "avatar"; img.alt = ""; const src = new URL(option.image_url); src.searchParams.set("width", "64"); src.searchParams.set("height", "64"); img.src = src.toString(); img.addEventListener("error", () => img.replaceWith(initials), { once: true }); return img;}アプリの DB には、メンバーの id だけを保存してください(タスクの担当者の列など)。image_url・name・email は保存しません。表示するたびに listMembers や getUser で最新の値を取得します。メンバーが画像を差し替えると、保存した値は古くなります。
ローカル開発
Section titled “ローカル開発”手元で動かすときは Keelson のログインがないため、ユーザー情報のヘッダーが付きません。keelson dev serve で起動すると本番と同じヘッダーが付き、閲覧のみの利用者と管理権限のある利用者を切り替えて確かめられます。CLI なしで KEELSON_LOCAL_MODE=1 を付けて起動したときは、Identity SDK が固定の 1 人を返します。手順はローカルで動かすを参照してください。
ローカルではカスタムグループを再現できません。グループごとの分岐は、実際の権限を設定したテスト用アプリでも確認してください。
Webhook などログインなしのリクエスト
Section titled “Webhook などログインなしのリクエスト”外部システムからアプリトークンで呼ばれる /api/external/ や /api/webhooks/ へのリクエストには、ログインユーザーの ID は渡されません。getCurrentUser や getCurrentIdentity で利用者を取得する処理とは分けて実装します。認証方法は外部システムとの連携を参照してください。
- グループとアプリ権限 — 誰に view / manage を与えるか
- 認証とログイン