Skip to content

M2M 组织成员管理接入指南

本文档面向第三方系统对接工程师,介绍如何通过 M2M(Machine-to-Machine)方式接入 Code Bird Cloud 的组织成员管理能力。

如果你的系统以前是通过组织角色名 adminorganization_roles 判断“组织管理员”,请先阅读 管理员身份判定迁移说明。当前组织管理员的最新判定方式是成员关系字段 is_admin

读完本文后,你应该可以完成以下事情:

  • 理解这套能力的鉴权模型
  • 让平台管理员在后台完成必要配置
  • 使用 client_credentials + organization_id 获取组织级 M2M Token
  • 调用组织成员查询、创建/加入、移除、角色查询、角色分配接口
  • 快速定位常见的 403 / 404 / 500 错误

适用场景

适合以下类型的集成:

  • 第三方 SaaS 平台同步组织成员到 Code Bird Cloud
  • 企业内部系统按组织批量创建、加入或维护成员
  • 第三方服务在特定组织上下文中查询成员和组织角色
  • 第三方服务根据业务数据自动调整组织成员角色

不适合以下场景:

  • 需要用户浏览器参与授权的场景
  • 需要邀请制入驻、邮件激活的场景
  • 需要第三方直接设置或取消组织管理员的场景

核心概念

1. 用户仍然是平台全局用户

Code Bird Cloud 中的用户不是“组织私有用户”。

同一个用户可以属于多个组织。M2M 创建成员时,本质上是:

  • 如果手机号不存在:创建一个平台用户,再加入当前组织
  • 如果手机号已存在:直接把已有平台用户加入当前组织

2. 组织管理员是成员关系上的独立标记

组织管理员不是第三方应用可操作的对象。

当前规则是:

  • 第三方应用可以查看管理员
  • 第三方应用不能移除管理员
  • 第三方应用不能设置管理员或取消管理员
  • 管理员只能由后台管理员在控制台中维护

3. 组织角色不直接等于权限

M2M 应用在组织里被分配的是“组织角色”,但真正用于鉴权的是这个角色背后绑定的 scope。

你可以这样理解:

  • 应用绑定到组织:决定这个应用能不能拿到该组织上下文的 Token
  • 给应用分配组织角色:决定这个应用在该组织内具备哪一类身份
  • 组织角色绑定 scope:决定这个应用最终能调用哪些 API

鉴权模型

M2M 组织成员管理接口使用组织级 M2M Token

请求链路

text
第三方应用
  -> 使用 client_credentials + organization_id 请求 Token
  -> Code Bird Cloud 校验应用是否绑定到该组织
  -> 加载该应用在该组织下的组织角色
  -> 从组织角色中解析 scope
  -> 返回带 organization_id 的 M2M Token
  -> 第三方应用携带 Bearer Token 调用 /api/v1/m2m/organizations/:organizationId/members...
  -> 服务端校验 token_type、organization_id、scope

M2M 成员接口的放行条件

请求必须同时满足:

  1. Token 为 M2M Token,即 token_type = "m2m"
  2. Token 内包含 organization_id
  3. Token 中的 organization_id 必须等于 URL 路径里的 organizationId
  4. Token scope 必须包含以下任一项:
    • manage:organizations
    • all

说明:组织级 M2M token 的 scopeaud 由“该应用在该组织下的组织角色”动态解析生成。 如果拿到的 token 中缺少这两个字段,优先检查组织绑定、应用角色分配和角色权限配置是否已正确保存。

其中:

  • manage:organizations 来自组织 Scope
  • all 来自 Management API Resource Scope

也就是说,这组 API 同时兼容两种组织级 Token:

  • 路径 A:组织 Scope Token
  • 路径 B:组织级 API 资源 Token

如果你只接这套组织成员管理接口,推荐优先使用路径 B:组织级 API 资源 Token,因为它更接近标准的 API 资源授权模型。

接入前准备

在第三方工程师调用接口前,平台管理员需要先完成后台配置。

方案一:通过管理后台配置

第 1 步:创建 M2M 应用

在「应用管理」中创建一个类型为 MachineToMachine 的应用,并保存:

  • Client ID
  • Client Secret

第 2 步:准备组织角色模板

在「组织模板」中创建或选择一个组织角色模板。

例如可以创建一个叫 org-member-manager 的角色模板。

第 3 步:给组织角色模板分配权限

有两种方式:

  • 方式 A:给组织角色绑定组织 Scope manage:organizations
  • 方式 B:给组织角色绑定 Management API 资源 Scope all

如果你要调用本文档中的 /api/v1/m2m/organizations/... 接口,至少需要其中一种。

第 4 步:将 M2M 应用绑定到目标组织

在「组织 -> 编辑组织 -> 机器对机器应用」中绑定目标应用。

第 5 步:给这个组织内的应用分配组织角色

仍在「组织 -> 编辑组织 -> 机器对机器应用」中,给该应用分配上一步准备好的组织角色。

只有做到这一步,请求 Token 时系统才会把对应 scope 放进 Token。

方案二:通过后台管理 API 预配置

如果你不通过控制台,也可以用管理 API 完成配置。

常用接口如下:

目的接口
创建组织角色模板POST /api/v1/organization-roles
给组织角色分配组织 ScopePUT /api/v1/organization-roles/{id}/scopes
给组织角色分配 API 资源 ScopePUT /api/v1/organization-roles/{id}/resource-scopes
绑定应用到组织POST /api/v1/organizations/{id}/applications
给组织中的应用分配组织角色PUT /api/v1/organizations/{id}/applications/{appId}/roles

这些接口需要管理员 Token,详细说明可结合以下文档阅读:

第一步:获取组织级 M2M Token

Token 端点:

http
POST /oidc/token
Content-Type: application/x-www-form-urlencoded

推荐方式:组织级 API 资源 Token

推荐请求:

http
grant_type=client_credentials&
client_id=YOUR_CLIENT_ID&
client_secret=YOUR_CLIENT_SECRET&
organization_id=ORG_ID&
resource=urn:codebird:management-api:YOUR_TENANT_ID

resource 必须传当前租户下真实存在的 Management API Resource Indicator。 可以直接从后台「授权 -> API 资源 -> Code Bird Management API」页面复制,格式通常为 urn:codebird:management-api:YOUR_TENANT_ID

兼容方式:组织 Scope Token

如果你的组织角色绑定的是 manage:organizations 这类组织 Scope,也可以不传 resource

http
grant_type=client_credentials&
client_id=YOUR_CLIENT_ID&
client_secret=YOUR_CLIENT_SECRET&
organization_id=ORG_ID

cURL 示例

bash
export BASE_URL="https://your-domain.com"
export CLIENT_ID="YOUR_CLIENT_ID"
export CLIENT_SECRET="YOUR_CLIENT_SECRET"
export ORG_ID="BxBgwQhpjDmtMpsLojRuj"
export RESOURCE="urn:codebird:management-api:YOUR_TENANT_ID"

ACCESS_TOKEN=$(curl -s -X POST "${BASE_URL}/oidc/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=${CLIENT_ID}" \
  -d "client_secret=${CLIENT_SECRET}" \
  -d "organization_id=${ORG_ID}" \
  -d "resource=${RESOURCE}" | jq -r '.access_token')

echo "${ACCESS_TOKEN}"

成功响应示例

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

Token 关键 Claims

json
{
  "sub": "JU_9INRc_cyTtDDw0U2dD",
  "client_id": "JU_9INRc_cyTtDDw0U2dD",
  "token_type": "m2m",
  "organization_id": "BxBgwQhpjDmtMpsLojRuj",
  "aud": ["urn:codebird:management-api:YOUR_TENANT_ID"],
  "scope": ["all"]
}

关键字段说明:

Claim说明
token_type固定为 m2m
organization_id当前 Token 所属组织
scope从“该应用在该组织下的组织角色”推导出来
aud如果传了 resource,这里就是该资源标识

第二步:调用组织成员管理 API

接口基准路径:

text
/api/v1/m2m/organizations/{organizationId}/members

统一请求头:

http
Authorization: Bearer <access_token>
Content-Type: application/json

统一成功响应格式:

json
{
  "code": 0,
  "result": {},
  "message": "success"
}

统一失败响应格式:

json
{
  "code": 41305,
  "result": null,
  "message": "组织管理员不允许由第三方应用移除"
}

API 1:查询组织成员列表

GET /api/v1/m2m/organizations/{organizationId}/members

分页查询当前组织下的成员。

查询参数

参数类型必填说明
pageinteger页码,默认 1
page_sizeinteger每页条数,默认 20
phonestring按手机号精确筛选
namestring按姓名模糊筛选
is_adminboolean按管理员标记筛选

cURL 示例

bash
curl -X GET "${BASE_URL}/api/v1/m2m/organizations/${ORG_ID}/members?page=1&page_size=20&is_admin=false" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}"

成功响应示例

json
{
  "code": 0,
  "message": "success",
  "result": {
    "total": 2,
    "data": [
      {
        "id": "_J4OiutDpPy_zl0kqNC_x",
        "username": "alice",
        "primary_phone": "13800000001",
        "primary_email": "alice@example.com",
        "name": "Alice",
        "is_admin": false,
        "joined_at": "2026-03-12T10:00:00Z",
        "created_at": "2026-03-12T10:00:00Z"
      }
    ],
    "page": 1,
    "page_size": 20
  }
}

字段说明

字段说明
id平台用户 ID
username用户名,可能为空
primary_phone用户主手机号
primary_email用户主邮箱,可能为空
name用户姓名
is_admin是否为组织管理员
joined_at加入当前组织的时间
created_at用户创建时间

API 2:按手机号创建或加入组织成员

POST /api/v1/m2m/organizations/{organizationId}/members

按手机号创建平台用户,或者复用已有平台用户并加入当前组织。

请求体

字段类型必填说明
phonestring用户手机号,作为主判定键
namestring用户姓名
emailstring用户邮箱,非主判定键

行为规则

  • 如果手机号不存在:创建新用户并加入当前组织
  • 如果手机号已存在:直接把该用户加入当前组织
  • 如果该用户已经在当前组织:接口仍返回成功

cURL 示例

bash
curl -X POST "${BASE_URL}/api/v1/m2m/organizations/${ORG_ID}/members" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "13800000002",
    "name": "Bob",
    "email": "bob@example.com"
  }'

成功响应示例

json
{
  "code": 0,
  "message": "success",
  "result": {
    "id": "user_bob_xxx",
    "username": "bob",
    "primary_phone": "13800000002",
    "primary_email": "bob@example.com",
    "name": "Bob",
    "is_admin": false,
    "joined_at": "2026-03-12T10:02:00Z",
    "created_at": "2026-03-12T10:02:00Z"
  }
}

第三方如需判断当前组织中的特殊成员,请仅使用 is_admin。 该字段表示“当前组织管理员”,不等同于平台后台超级管理员。


API 3:移除组织成员

DELETE /api/v1/m2m/organizations/{organizationId}/members/{userId}

移除当前组织中的一个普通成员,同时清除该成员在本组织内的组织角色分配。

cURL 示例

bash
curl -X DELETE "${BASE_URL}/api/v1/m2m/organizations/${ORG_ID}/members/${USER_ID}" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}"

成功响应示例

json
{
  "code": 0,
  "message": "success",
  "result": null
}

限制

  • 不能移除组织管理员
  • 只能移除当前组织中的成员
  • 不会删除平台用户本身,只会删除该用户与当前组织的关系

API 4:查询成员在当前组织内的角色

GET /api/v1/m2m/organizations/{organizationId}/members/{userId}/roles

查询某个成员在当前组织中的角色列表。

cURL 示例

bash
curl -X GET "${BASE_URL}/api/v1/m2m/organizations/${ORG_ID}/members/${USER_ID}/roles" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}"

成功响应示例

json
{
  "code": 0,
  "message": "success",
  "result": [
    {
      "id": "role_member_manager",
      "name": "member-manager",
      "description": "Can manage organization members",
      "type": "User",
      "created_at": "2026-03-01T08:00:00Z"
    }
  ]
}

API 5:替换成员在当前组织内的角色

PUT /api/v1/m2m/organizations/{organizationId}/members/{userId}/roles

全量替换成员在当前组织中的角色分配。

请求体

字段类型必填说明
role_idsstring[]组织角色 ID 列表

cURL 示例

bash
curl -X PUT "${BASE_URL}/api/v1/m2m/organizations/${ORG_ID}/members/${USER_ID}/roles" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "role_ids": ["role_member_manager", "role_viewer"]
  }'

成功响应示例

json
{
  "code": 0,
  "message": "success",
  "result": null
}

行为说明

  • 这是“替换”而不是“增量追加”
  • 新列表会覆盖该成员在当前组织中的旧角色列表
  • 不会影响该用户在其他组织中的角色

推荐接入流程

建议第三方系统按以下顺序实现:

  1. 平台管理员完成 M2M 应用、组织角色、scope、组织绑定配置
  2. 第三方系统调用 /oidc/token 获取组织级 M2M Token
  3. 调用成员列表接口确认当前组织成员现状
  4. 如需新增成员,调用“按手机号创建或加入组织成员”
  5. 如需调整角色,调用成员角色查询与角色替换接口
  6. 如需移除成员,先确认该成员不是管理员,再调用删除接口

常见错误与排查

1. 403 应用未绑定到该组织

说明请求 Token 时,M2M 应用还没有绑定到该组织。

检查:

  • 后台是否已将该应用绑定到目标组织
  • organization_id 是否填写正确

2. 403 组织上下文不匹配

说明 Token 里的 organization_id 与 URL 里的 {organizationId} 不一致。

检查:

  • 申请 Token 时传入的 organization_id
  • 调用 API 时的路径参数

3. 403 权限不足

说明当前 Token 虽然是组织级 Token,但 scope 不够。

检查:

  • 该应用在该组织下是否分配了组织角色
  • 该组织角色是否绑定了 manage:organizations
  • 或该组织角色是否绑定了 Management API 的 all 资源 scope

4. 403 组织管理员不允许由第三方应用移除

说明目标成员是组织管理员。

处理方式:

  • 先由后台管理员在控制台调整管理员身份
  • 或跳过该成员,不通过第三方接口移除

5. 404 组织不存在

说明路径里的组织 ID 不存在。

6. 404 组织成员不存在

说明目标用户不在该组织下,或者 userId 写错。

错误码参考

M2M 组织成员接口错误码

错误码HTTP 状态说明
41300500获取组织成员列表失败
41301404组织成员不存在
41302500创建或加入组织成员失败
41303500移除组织成员失败
41304500分配组织成员角色失败
41305403组织管理员不允许由第三方应用移除

组织相关通用错误码

错误码HTTP 状态说明
41000404组织不存在

鉴权层常见错误消息

HTTP 状态消息
403仅支持机器对机器应用访问
403组织上下文不匹配
403权限不足

最小可运行示例

下面是一个典型的自动同步流程:

bash
#!/usr/bin/env bash
set -euo pipefail

BASE_URL="https://your-domain.com"
CLIENT_ID="YOUR_CLIENT_ID"
CLIENT_SECRET="YOUR_CLIENT_SECRET"
ORG_ID="BxBgwQhpjDmtMpsLojRuj"
RESOURCE="urn:codebird:management-api:YOUR_TENANT_ID"
PHONE="13800000003"
NAME="Charlie"

ACCESS_TOKEN=$(curl -s -X POST "${BASE_URL}/oidc/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=${CLIENT_ID}" \
  -d "client_secret=${CLIENT_SECRET}" \
  -d "organization_id=${ORG_ID}" \
  -d "resource=${RESOURCE}" | jq -r '.access_token')

MEMBER=$(curl -s -X POST "${BASE_URL}/api/v1/m2m/organizations/${ORG_ID}/members" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{\"phone\":\"${PHONE}\",\"name\":\"${NAME}\"}")

USER_ID=$(echo "${MEMBER}" | jq -r '.result.id')

curl -s -X PUT "${BASE_URL}/api/v1/m2m/organizations/${ORG_ID}/members/${USER_ID}/roles" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"role_ids":["role_member_manager"]}'

与其他文档的关系

建议按这个顺序阅读:

  1. M2M 认证指南
  2. M2M 组织级 Token
  3. 本文档:组织成员管理接入
  4. Management API 交互
  5. 组织管理 API

Released under the MIT License.