ユーザーの代理として動作する
オリジン は Early Beta 段階にあり、今後変更される可能性があります。
オリジン App は、インストールユーザートークンを使用して、インストール先の名前空間のメンバーの代理として動作します。各リクエストで実行できる操作は、インストールとユーザーの両方が持つ権限の範囲内に限られます。
オリジン API の base URL とエラーモデルを使用します。トークンはアプリ JWT で発行します。
仕組み
- Workspace 管理者が、アプリのインストールに対して
namespace:user_tokens:writeスコープを承認します。 - 必要に応じて、ユーザーの Cherri Code ID を確認します。オリジンは、そのユーザーの
user_…ID を含む署名付きレシートを返します。 - アプリ JWT に署名し、ユーザーの ID またはメールアドレスを指定してインストールユーザートークンを発行します。
expiresAtまでインストールユーザートークンを使用して REST API または Git over HTTPS にアクセスし、期限が切れたら新しいトークンを発行します。
スコープをリクエストする
インストールURL の scope パラメータに namespace:user_tokens:write を追加します。既存のインストールの場合は、include_granted_scopes=true もあわせて送信してください。これにより、管理者は追加分だけを承認すれば済みます。
/codebase/apps/install ?client_id=APP_ID &scope=namespace:user_tokens:write%20repository:pull_requests:write &redirect_uri=REGISTERED_CALLBACK &state=RANDOM_ANTI_FORGERY_VALUE &include_granted_scopes=trueこのスコープにより、インストールはその名前空間内の任意の有効なメンバーに対してトークンを発行できるようになります。トークンの scopes に含めることはできません。管理者が承認したその他のスコープは、引き続き各トークンの権限の上限となります。
ユーザーを確認するタイミング
ユーザー確認は任意です。管理者が namespace:user_tokens:write を承認すれば、名前空間のすべてのメンバーが対象になります。
自社プロダクトのアカウントをユーザーの Cherri Code アカウントに連携したい場合や、入力されたメールアドレスをそのまま信頼せずに ID を確認したい場合は、ユーザー確認を行います。レシートは、確認時点におけるサインイン中ユーザーの user_… ID、メールアドレス、名前空間のメンバーシップを証明します。
レシートは ID を証明するだけで、権限を付与するものではありません。Create Installation User Token はレシートを受け付けず、必要ともしません。
ユーザー確認
ユーザーをオリジンに誘導する
ユーザーのブラウザで次のURLを開きます:
/codebase/apps/user-confirmation ?installation_id=INSTALLATION_ID &redirect_uri=REGISTERED_CALLBACK &state=RANDOM_ANTI_FORGERY_VALUE| パラメータ | 必須 | 説明 |
|---|---|---|
installation_id | はい | ユーザーの名前空間にあるアプリの有効なインストールの i_… ID。 |
redirect_uri | はい | コールバック URI。アプリの installationRedirectUris (インストールフローの許可リスト) のいずれかのエントリと完全に一致する必要があります。 |
state | 強く推奨 | ランダムな偽造防止用の値。確認レシートの state クレームとしてそのまま返されます。 |
各パラメータは 1 回だけ送信してください。必須パラメータが不足している場合やパラメータが重複している場合は、サインイン後にエラーになります。
ユーザーに表示される内容
サインアウト状態のユーザーは Cherri Code にサインインした後、パラメータを保持したまま同じリンクに戻ります。オリジンはサインイン後にパラメータを検証するため、形式が正しくないリンクであっても、サインインを済ませてからエラーが表示されます。
オリジンには、アプリの名前、アイコン、説明が、インストール先の名前空間とともに表示されます。また、アプリが受け取る情報も一覧表示されます:
- Cherri Code の数値ユーザー ID (
user_…) - メールアドレス
- オリジン名前空間の slug と ID
このページでは、確認すると ID と現在の名前空間のメンバーシップが共有されるものの、リポジトリへのアクセス権限は付与されないことが説明されます。ユーザーは Confirm または Cancel を選択します。
確認できるのは、所有チームの有効なメンバー、または個人の名前空間の所有者のみです。
コールバック
確認が完了すると、オリジンは指定されたコールバックにリダイレクトします:
https://app.example.com/origin/confirm?confirmation_receipt=RECEIPT_JWT&state=RANDOM_ANTI_FORGERY_VALUE確認レシートを検証してから、そのユーザークレームを読み取ります。コールバックに state が含まれるのは、確認 URL で空でない値が指定されていた場合のみです。クエリパラメータではなく、署名済みの state クレームを信頼してください。
キャンセルした場合や確認を完了できなかった場合、コールバックもリダイレクトも発生しません。コールバックが届かない場合は「未確認」として扱い、ユーザーが最初からやり直せるようにしてください。
確認レシート
confirmation_receipt は、インストールレシートと同じ鍵でオリジンが署名したコンパクトな JWT です。
JOSE ヘッダー:
{ "alg": "EdDSA", "kid": "origin-key-id", "typ": "origin-user-confirmation-receipt+jwt"}クレーム:
{ "iss": "https://api.cursor.com/v1/origin", "aud": "app_01...", "sub": "user_01...", "installation_id": "i_01...", "namespace_id": "ns_01...", "email": "[email protected]", "iat": 1786465200, "exp": 1786465500, "jti": "RECEIPT_UUID", "state": "ORIGINAL_VALUE"}audはアプリ ID です。subは確認済みユーザーのuser_…ID で、トークンを発行する際にuserIdとして使用します。installation_idとnamespace_idは、メンバーシップが確認されたインストールと名前空間を識別します。emailは、確認時点でのユーザーのアカウントのメールアドレスです。- レシートの有効期限は発行から 5 分間です。
jtiはレシートごとに一意です。 stateは、確認 URL で空でない値が指定された場合にのみ含まれます。
コールバックを信頼する前に、レシートを確認してください。
kidヘッダーをもとに、JWKS から署名キーを取得します。- 確認レシートをインストールレシートやアクセストークンと区別するため、
alg: EdDSAとtyp: origin-user-confirmation-receipt+jwtを必須とします。 - 署名、
iss、aud、expを検証します。 installation_idと署名済みのstateが、送信した値と一致することを確認します。
いずれかのチェックに失敗した場合は、コールバックを拒否してください。
確認エラー
エラーが発生した場合は Cherri Code のページから遷移せず、コールバックは呼び出されません。
| エラー | 原因 |
|---|---|
| 無効なリンク | installation_id または redirect_uri が指定されていないか空になっている、またはパラメータが重複しています。 |
| 承認されていません | インストールが存在しないか有効になっていない、redirect_uri がアプリに登録されていない、またはユーザーがインストールの名前空間のメンバーではありません。どの原因に該当するかはページに表示されません。 |
| 一時的に利用できません | 確認後、オリジンがレシートに署名できませんでした。ユーザーは再試行できます。 |
インストールユーザートークンを発行する
アプリ JWT を使用して Create Installation User Token (POST /v1/origin/app/installations/{installationId}/user_access_tokens) を呼び出します。userId と userEmail のどちらか一方のみを指定してください。
curl --request POST \ --url 'https://api.cursor.com/v1/origin/app/installations/INSTALLATION_ID/user_access_tokens' \ --header 'Authorization: Bearer APP_JWT' \ --header 'Content-Type: application/json' \ --data '{ "userId": "user_01...", "scopes": [ "repository:pull_requests:write" ], "repositoryIds": [ "repo_01..." ]}'{ "token": "YOUR_INSTALLATION_USER_TOKEN", "expiresAt": "2026-01-01T00:15:00Z"}| フィールド | 説明 |
|---|---|
userId | 確認レシートの sub またはアクターのペイロードから取得した、ユーザーの user_… ID。 |
userEmail | ユーザーのアカウントのメールアドレス。インストールの名前空間に属する有効なメンバーのうち、1 人だけに一致する必要があります。 |
scopes | 任意の上限。値は重複不可で、インストールに対して承認されている必要があります。namespace:user_tokens:write、および app: または installation: のプレフィックスが付いたスコープは委任できません。空または省略した場合は、現在の権限が使用されます。 |
repositoryIds | 任意の上限。インストールからアクセス可能な重複しないリポジトリ ID を最大 50 件まで指定できます。空または省略した場合は、現在の権限が使用されます。 |
ユーザーは有効な Cherri Code アカウントを持ち、名前空間のメンバーシップ要件を満たしている必要があります。不明なユーザー、メンバーでないユーザー、複数のメンバーに一致するメールアドレスのいずれの場合も、同じ 403 が返されます。
scopes と repositoryIds の両方を指定した場合、指定したすべてのリポジトリについて、インストールとユーザーの双方が要求されたすべてのスコープを保持している場合にのみ発行が成功します。上限の指定が少ない場合は、リクエストのたびに権限がチェックされます。
有効期間
expiresAt は発行から最大 15 分後で、アプリ JWT の exp を超えることはありません。これは インストールアクセストークン と同様です。リフレッシュトークンはありません。有効期限が切れたら、新しいアプリ JWT でトークンを再発行してください。発行のたびに、アプリ JWT の レート制限 から 1 ポイントが消費されます。
トークンを使用する
インストールユーザートークンは不透明なものとして扱い、そのコンテンツを検査・解析しないでください。トークンは、REST API に対しては Bearer 認証情報として、Git over HTTPS に対してはユーザー名 x-access-token のパスワードとして送信します:
Authorization: Bearer YOUR_INSTALLATION_USER_TOKEN各リクエストは、インストールの承認済みスコープとリポジトリ選択、ユーザーのオリジン の権限付与、およびトークンの上限の範囲内である必要があります。満たさない場合は 403 が返されます。リソースが参照できない場合は 404 が返されます。
アクターのフィールドはユーザーを示し、アプリの id と省略可能な displayName を含む performedVia.app が含まれる場合があります。帰属情報は、そのフィールドが表すアクションに対して適用されます。たとえばコメントの作成者に含まれている場合は、そのコメントを作成したアプリを示します。後からコメントを編集または削除したアプリを示すものではありません。ユーザーが直接行ったアクションでは performedVia は含まれません。また、委任データが利用できない場合も含まれないことがあります。
発行時のエラー
| HTTP ステータス | 原因 |
|---|---|
400 | userId と userEmail のうち一方だけが設定されていない (両方未設定、または両方設定) 、無効な user_… ID またはメールアドレスを使用している、重複・形式不正・委任不可のスコープを含んでいる、またはリポジトリ ID の重複や 50 個を超えるリポジトリ ID を含んでいる。 |
401 | アプリ JWT が無効または期限切れである。あるいはインストールが存在しない、別のアプリに属している、または停止されている。 |
403 | インストールに namespace:user_tokens:write がない、要求した上限がインストールに付与された権限の範囲を超えている、ユーザーが対象外である、または両方の上限を指定したリクエストに、インストールかユーザーのいずれかが持たない権限が含まれている。 |
429 | アプリ JWT のレート制限に達した。制限の超過を参照してください。 |
503 | オリジンがユーザーの検索またはトークンの署名に失敗した。バックオフを使用して再試行してください。 |
失効
トークンを個別に失効させることはできません。次の変更はトークンのアクセスに影響します。
- アプリをアンインストールまたは削除すると、そのアプリのユーザートークンは
expiresAtを待たずに無効になります。リクエストには401が返されます。 - ユーザーの Cherri Code アカウントを閉鎖すると、そのユーザーのトークンは無効になります。リクエストには
401が返されます。 namespace:user_tokens:writeを削除するか、インストールを一時停止すると、新しいトークンは発行されなくなります。発行済みのトークンはexpiresAtの時点で期限切れになります。- インストールまたはユーザーの権限付与の変更は、遅くとも
expiresAtまでに反映されます。
セキュリティに関する注意事項
- トークンは必要になった時点で、必要最小限の
scopesとrepositoryIdsを指定して発行してください。トークンはパスワードと同様に扱い、保存やログへの記録は行わないでください。 - 連携アカウントのキーには
emailではなくsubを使用してください。ユーザーのuser_…ID は変わりませんが、メールアドレスは変更される可能性があります。 userEmailを指定して発行する前に、メールアドレスを確認してください。入力されたアドレスが別のメンバーを指している可能性があります。- 各レシートは 1 回だけ使用してください。
jtiを記録し、5 分間の有効期間内に同じものが再度使われた場合は拒否してください。 - レシートは認証情報ではありません。ユーザーのメールアドレスが含まれているため、Bearer token として送信したり、ログに記録したりしないでください。
- レシートは確認時点のメンバーシップを表します。トークンを発行するたびにメンバーシップが再確認されるため、保存済みのレシートがあっても、すでに退出したユーザーのトークンは発行できません。