---
title: 登录授权
description: 宿主把用户登录到内嵌 PAC 的换票接口、请求参数与数据权限填法。
icon: KeyRound
---

> PAC 工作台以 iframe 嵌入宿主系统。用户在宿主侧登录后,宿主**换票**给 PAC —— 传入「身份 + 角色 + 可见范围」,换取一次性 code 打开 PAC 页面。
> 接口与字段以 [API 参考 · auth](/docs/api/auth/AuthController_exchangeToken) 的 OpenAPI 定义为准。

---

## 接入前提

接入时由 PAC 分配一对 **`appId` + `appSecret`**;`appSecret` 仅宿主服务端持有,不下发到浏览器。

## 换票流程

```
① 宿主服务端   POST /pac/v1/auth/token   { appId, appSecret, user }
                                          → { code, accessToken, refreshToken, ... }
② 宿主前端     用 code 拼 PAC 页面 URL 打开 iframe(一次性,默认 60 秒有效)
```

`code` 具体怎么拼进 iframe URL、嵌哪条路径,见[接入总览 · iframe 嵌入](/docs/integration/overview#5-iframe-嵌入客服界面接入方式)。

三个凭证的有效期各不相同,过期后需重新走对应流程:

| 凭证 | 有效期 | 过期后 |
|---|---|---|
| `code` | 60 秒(一次性,用后即焚)| 重新调 `/auth/token` 换新 code |
| `accessToken` | 2 小时 | 用 `refreshToken` 调 `/auth/refresh` 静默续期 |
| `refreshToken` | 7 天 | 需重新走换票流程 |

iframe 内的 token 落地与刷新由 PAC 前端完成。`refreshToken` 过期(或用户超 7 天未打开)后,PAC 前端会引导用户回宿主侧重新进入触发换票。

---

## 接口:`POST /pac/v1/auth/token`

完整定义见 [API 参考 · auth](/docs/api/auth/AuthController_exchangeToken)。

### 请求参数

```jsonc
{
  "appId":     "app_xxxxxx",
  "appSecret": "***",
  "user": {
    "userId":   "u_10086",
    "tenantId": "grp_001",
    "role":     "leader",
    "orgScope": ["B001"],
    "dictionary": {
      "clinics": { "C001": "（门店名）" },
      "users":   { "u_10086": "（用户名）" }
    }
  }
}
```

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `appId` | string | ✅ | PAC 分配给宿主的应用标识 |
| `appSecret` | string | ✅ | 与 `appId` 配对的密钥,**仅宿主服务端持有**,不下发到浏览器 |
| `user.userId` | string | ✅ | 宿主侧登录用户的唯一 id|
| `user.tenantId` | string | ✅ | 集团 id(组织树的根);单集团宿主固定用一个值。宿主侧有集团id就传id，没有传唯一slug如appId |
| `user.role` | string | ✅ | 功能权限:`staff` / `leader` / `admin`。见下「`role`」 |
| `user.orgScope` | string[] | ✅ | 数据权限:用户可达的组织节点 id 列表;传 `[]` = 全集团不限。见下「`tenantId` 与 `orgScope`」 |
| `user.dictionary` | object | 选填 | `id → 名` 映射,仅用于页面把 id 显示成名字,**不影响权限**。含 `clinics`、`users` 两个子字典。建议提供,否则页面显示原始 id |

> `orgScope` 字段本身必传(哪怕是空数组);请求体为严格模式,未定义的字段会被拒绝。

**`role`** — 功能权限:

| 角色 | 范围 |
|---|---|
| `staff` | 执行客服:查看 / 认领 / 执行自己的召回工单 |
| `leader` | 主管:在 staff 基础上增加全池查看 / 分配 / 回收 / 统计 |
| `admin` | 后台管理员:全部 |

**`tenantId` 与 `orgScope` —— 宿主侧组织 id**。PAC理解宿主（SaaS）组织是一棵树,根 = 集团(`tenantId`),往下品牌 / 区域 / 诊所等（仅举例）;`orgScope` 是用户可达的节点（数据权限）:

| 用户 | `orgScope` |
|---|---|
| 集团管理员 | `[]`(空 = 全集团) |
| 品牌主管 | `["B001"]`(品牌 → 含其下全部诊所) |
| 区域负责人 | `["R-East"]`(区域 → 含其下全部品牌与诊所) |
| 诊所客服 | `["C001", "C002"]`(诊所) |

> 如 `orgScope` 为 `["B001", "C002"]`,可看到的是 B001 下和 C002 下的数据(多个节点取并集)

### 响应参数

```jsonc
{
  "code":          "...",   // 一次性 code,拼进 PAC iframe URL(默认 60 秒)
  "codeExpiresIn": 60,
  "accessToken":   "...",   // 供宿主服务端直连 PAC API(Bearer);iframe 模式可忽略
  "refreshToken":  "...",
  "expiresIn":     7200     // accessToken 有效期(秒)
}
```

iframe 嵌入只需 `code`;`accessToken` / `refreshToken` 供服务端直连 API 时使用。响应字段后续可能扩展,消费方应忽略未知字段。
