---
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",     // PAC 分配
  "appSecret": "***",            // 配对密钥,仅服务端持有
  "user": {
    "userId":   "u_10086",       // 宿主侧用户唯一 id
    "tenantId": "grp_001",       // 集团 id(见下)
    "role":     "leader",        // staff | leader | admin
    "orgScope": ["B001"],        // 数据权限(见下)
    "dictionary": {              // 可选:id→名,用于页面把 id 显示成名字
      "clinics": { "C001": "（门店名）" },
      "users":   { "u_10086": "（用户名）" }
    }
  }
}
```

请求体为严格模式,未定义字段会被拒绝。

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

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

**`tenantId` 与 `orgScope` —— 同一套组织 id**。宿主组织是一棵树,根 = 集团(`tenantId`),往下品牌 / 区域 / 诊所;`orgScope` 是用户可达的节点:

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

取值用 PAC 摄入数据里的同一套 id(集团 = `tenant_id`、品牌 = `source_unit`、诊所 = `clinic_id`):**换票传的与该环境数据对得上即可命中**,与"环境"无关。单集团宿主 `tenantId` 用一个固定值。

### 响应参数

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

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