跳至主要內容

自動化租戶管理

你可以以程式化方式管理 Logto Cloud 租戶,包括建立租戶並持續進行設定,無需切換到 Console。

當你需要從自己的導入流程、內部平台、AI agent 或整合自動化中佈建租戶時,這會非常有用。

自動化流程如下:

  1. 使用 Logto Cloud Personal Access Token (PAT) 呼叫 Logto Cloud API。
  2. 透過 POST /api/tenants 建立租戶。
  3. 從建立回應中讀取預設機器對機器 (M2M) 應用程式憑證。
  4. 使用預設 M2M 應用程式取得新租戶的 Management API 存取權杖 (Access token)。
  5. 呼叫新租戶的 Management API,持續佈建應用程式、使用者、角色 (Roles)、資源 (Resources)、組織 (Organizations) 及其他設定。

建立 PAT​

為你的 Logto Cloud 帳號建立個人存取權杖 (PAT):

  1. 在 Logto Cloud Console,點擊右上角頭像並選擇 個人檔案 (Profile)。
  2. 開啟 安全性 (Security) 頁面。
  3. 在 Personal access tokens 區塊,點擊 Create new token。
  4. 輸入名稱並選擇最長 365 天的到期日,然後確認。

權杖只會在建立後顯示一次。請複製並妥善保存於安全處(如秘密管理工具)。你將無法再次查看。

建議設為 90 天到期,並在到期前輪替權杖。你可以在同一頁面重新命名或撤銷權杖。

撤銷權杖約在一分鐘內生效。

PAT 可呼叫需要 create:tenant 或 manage:tenant:self 權限範圍 (Scope) 的 Cloud API 路徑:

  • GET /api/me/regions:列出帳號可用的區域。
  • POST /api/tenants:建立租戶。
  • GET /api/tenants:列出你的租戶,PATCH 或 DELETE /api/tenants/{tenantId}:重新命名或刪除租戶。
  • POST /api/tenants/{tenantId}/subscription 及 /api/tenants/{tenantId} 下的其他端點:管理租戶方案、發票與電子郵件日誌。

需要 manage:account:self 權限範圍的路徑(如帳單、授權、Console SSO)需互動式 Console 工作階段,無法用 PAT 呼叫。

開始前準備​

請準備以下變數:

變數說明
CLOUD_API_ENDPOINTLogto Cloud API 端點。Logto Cloud 請用 https://cloud.logto.io。
LOGTO_CLOUD_PAT你的 Logto Cloud 帳號 PAT。
TENANT_NAME要建立的租戶顯示名稱。
TENANT_TAG租戶型態。請用 development 或 production。
REGION_NAME租戶所屬區域識別碼。

將它們設為環境變數:

export CLOUD_API_ENDPOINT="https://cloud.logto.io"
export LOGTO_CLOUD_PAT="<logto-cloud-pat>"
export TENANT_NAME="My automated tenant"
export TENANT_TAG="development"
export REGION_NAME="<region-name>"

取得可用區域​

建立租戶前,先查詢你的 Logto Cloud 帳號可用的區域:

curl "$CLOUD_API_ENDPOINT/api/me/regions" \
-H "Authorization: Bearer $LOGTO_CLOUD_PAT"

回應內容包含可用區域。建立租戶時,請將 name 欄位值作為 REGION_NAME。

範例回應:

{
"regions": [
{
"name": "EU",
"displayName": "Europe"
},
{
"name": "US",
"displayName": "United States"
}
]
}

建立租戶​

使用 Logto Cloud PAT 呼叫 POST /api/tenants:

curl "$CLOUD_API_ENDPOINT/api/tenants" \
-X POST \
-H "Authorization: Bearer $LOGTO_CLOUD_PAT" \
-H "Content-Type: application/json" \
-d '{
"name": "'"$TENANT_NAME"'",
"tag": "'"$TENANT_TAG"'",
"regionName": "'"$REGION_NAME"'"
}'

回應內容包含新建立的租戶及預設 M2M 應用程式。該 M2M 應用程式建立於新租戶中,並可存取該租戶的 Management API。

範例回應:

{
"id": "new-tenant-id",
"name": "My automated tenant",
"tag": "development",
"indicator": "https://new-tenant-id.logto.app",
"regionName": "EU",
"defaultApplication": {
"id": "default-m2m-app-id",
"secret": "default-m2m-app-secret"
}
}

將你需要的值存下來以便下一步使用:

export TENANT_ID="<response.id>"
export TENANT_ENDPOINT="<response.indicator>"
export DEFAULT_M2M_APP_ID="<response.defaultApplication.id>"
export DEFAULT_M2M_APP_SECRET="<response.defaultApplication.secret>"
提示:

以 tag: "production" 建立的租戶會預設啟用 Free 方案。若要在同一腳本中升級至 Pro 方案,請參考 訂閱 Pro 方案。像本例的開發租戶 (development tenant) 則無法透過 API 訂閱。

取得新租戶的 Management API 存取權杖 (Access token)​

使用預設 M2M 應用程式憑證,向新租戶請求存取權杖:

curl "$TENANT_ENDPOINT/oidc/token" \
-X POST \
-u "$DEFAULT_M2M_APP_ID:$DEFAULT_M2M_APP_SECRET" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "resource=$TENANT_ENDPOINT/api" \
-d "scope=all"

範例回應:

{
"access_token": "eyJ...",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "all"
}

儲存 access token:

export MANAGEMENT_API_ACCESS_TOKEN="<response.access_token>"

持續佈建新租戶​

使用 Management API 存取權杖呼叫新租戶的 Management API。

例如,列出應用程式:

curl "$TENANT_ENDPOINT/api/applications" \
-H "Authorization: Bearer $MANAGEMENT_API_ACCESS_TOKEN"

或建立一個應用程式:

curl "$TENANT_ENDPOINT/api/applications" \
-X POST \
-H "Authorization: Bearer $MANAGEMENT_API_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My web app",
"type": "SPA",
"oidcClientMetadata": {
"redirectUris": ["https://example.com/callback"],
"postLogoutRedirectUris": ["https://example.com"]
}
}'

此時,你的自動化流程可繼續進行任何 Management API 操作,例如建立使用者、應用程式、API 資源 (API resources)、角色 (Roles)、組織 (Organizations)、連接器 (Connectors) 或登入體驗 (Sign-in experience) 設定。

完整自動化範例​

以下 Node.js 範例會建立租戶、用預設 M2M 憑證換取 Management API 存取權杖,並列出新租戶的應用程式:

const cloudApiEndpoint = 'https://cloud.logto.io';
const logtoCloudPat = process.env.LOGTO_CLOUD_PAT;

const createTenantResponse = await fetch(`${cloudApiEndpoint}/api/tenants`, {
method: 'POST',
headers: {
authorization: `Bearer ${logtoCloudPat}`,
'content-type': 'application/json',
},
body: JSON.stringify({
name: 'My automated tenant',
tag: 'development',
regionName: 'EU',
}),
});

if (!createTenantResponse.ok) {
throw new Error(`Failed to create tenant: ${await createTenantResponse.text()}`);
}

const tenant = await createTenantResponse.json();
const tenantEndpoint = tenant.indicator;
const { id: appId, secret: appSecret } = tenant.defaultApplication;

const tokenResponse = await fetch(`${tenantEndpoint}/oidc/token`, {
method: 'POST',
headers: {
authorization: `Basic ${Buffer.from(`${appId}:${appSecret}`).toString('base64')}`,
'content-type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'client_credentials',
resource: `${tenantEndpoint}/api`,
scope: 'all',
}),
});

if (!tokenResponse.ok) {
throw new Error(`Failed to get Management API token: ${await tokenResponse.text()}`);
}

const { access_token: managementApiAccessToken } = await tokenResponse.json();

const applicationsResponse = await fetch(`${tenantEndpoint}/api/applications`, {
headers: {
authorization: `Bearer ${managementApiAccessToken}`,
},
});

if (!applicationsResponse.ok) {
throw new Error(`Failed to list applications: ${await applicationsResponse.text()}`);
}

const applications = await applicationsResponse.json();

console.log({ tenantId: tenant.id, applications });