# iOS 登录流程 —— 总体设计

---

## 一、核心理解

```
Apple 登录不是你的 App 登录系统本身。
Apple 只是帮你证明"这个人是谁"。
真正的登录态，要由你的后端发 accessToken / refreshToken。
```

最终流程：

```
iOS 调 Apple 登录
→ 拿到 Apple identityToken
→ 发给你的 NestJS 后端
→ 后端校验 Apple token
→ 后端创建 / 查找用户
→ 后端生成自己的 accessToken + refreshToken
→ iOS 存 Keychain
→ 以后所有接口带 Authorization: Bearer accessToken
```

**开发建议**：先做 `dev-login → /users/me → Keychain → 知识库接口`，Apple 登录随后再接，不要让 Apple 流程卡住后端开发。

---

## 二、认证系统核心模型

后端登录系统的本质是建立自己的认证体系：

```
users
+ auth_accounts           （支持多 provider：DEV、APPLE）
+ refresh_tokens          （只存 hash，不存明文）
+ accessToken             （短期令牌，JWT）
+ refreshToken            （长期令牌，JWT，可轮换/撤销）
+ JwtAuthGuard            （全局守卫）
+ /users/me               （启动态判定核心接口）
```

Apple 登录只是其中一个 provider。核心是通过 `auth_accounts` 表关联第三方身份与本地用户。

---

## 三、接口清单

第一版 5 个接口：

| 接口 | 用途 | 优先级 |
|------|------|--------|
| `POST /api/auth/dev-login` | 开发调试登录 | ⭐ 先做 |
| `POST /api/auth/refresh` | 刷新登录态 | ⭐ 先做 |
| `GET /api/users/me` | 获取当前用户 | ⭐ 先做 |
| `POST /api/auth/apple` | Apple 正式登录 | 随后接 |
| `POST /api/auth/logout` | 退出登录 | 最后做 |

---

## 四、统一返回格式

登录成功后后端统一返回：

```json
{
  "accessToken": "eyJ...",
  "refreshToken": "eyJ...",
  "user": {
    "id": "user_xxx",
    "email": "test@zhixi.app",
    "nickname": "测试用户",
    "avatarUrl": null,
    "role": "USER",
    "status": "ACTIVE",
    "onboardingCompleted": false
  }
}
```

iOS 拿到后：

| 数据 | 存储位置 | 用途 |
|------|---------|------|
| `accessToken` | 内存 | 接口请求 Authorization Header |
| `refreshToken` | Keychain | 恢复登录 |
| `user` | AppSession / UserStore | 用户信息展示 |

---

## 五、后端模块结构

```
src/modules/auth/
├── auth.controller.ts          # 登录/刷新/登出接口
├── auth.service.ts             # 通用登录逻辑（provider 调度）
├── apple-auth.service.ts       # Apple identityToken 校验
├── token.service.ts            # JWT 生成/校验
├── dto/
│   ├── dev-login.dto.ts
│   ├── apple-login.dto.ts
│   └── refresh-token.dto.ts
├── guards/
│   └── jwt-auth.guard.ts       # 全局认证守卫
├── decorators/
│   └── current-user.decorator.ts    # 从 JWT 取用户
└── strategies/
    └── jwt.strategy.ts

src/modules/users/
├── users.controller.ts         # /users/me
├── users.service.ts
└── dto/
```

---

## 六、业务接口安全规则

所有业务接口依赖登录体系。**核心规则：不要相信前端传的 `userId`。**

```http
GET /api/knowledge-bases
Authorization: Bearer accessToken
```

后端应从 JWT 拿当前用户：

```ts
// ✅ 正确：从 token 里取 currentUser.id
where: {
  userId: currentUser.id,
  deletedAt: null
}

// ❌ 错误：从请求体取 userId
where: {
  userId: body.userId
}
```

用户资源接口，只相信 JWT 里的 `currentUser.id`，不允许前端传递 `userId` 参数。

---

## 七、推荐开发顺序

```
1. Prisma 建 users / auth_accounts / refresh_tokens
2. TokenService：生成 accessToken / refreshToken
3. dev-login 接口
4. JwtAuthGuard
5. CurrentUser 装饰器
6. /users/me 接口
7. iOS 接 dev-login + Keychain + AppSession
8. 知识库接口全部加 JwtAuthGuard
9. Apple 登录接口
10. refresh 接口
11. logout 接口
```

---

## 八、环境变量最小配置

```env
JWT_ACCESS_SECRET=你自己的随机强密钥
JWT_REFRESH_SECRET=你自己的随机强密钥
APPLE_BUNDLE_ID=cloud.longde.AIStudyApp
APPLE_ISSUER=https://appleid.apple.com
APPLE_JWKS_URL=https://appleid.apple.com/auth/keys
```

---

## 九、总结

最终一句话：后端登录对接的核心不是"接 Apple 登录按钮"，而是先建立自己的认证系统。Apple 登录只是其中一个 provider。先把 `dev-login → token → /users/me → iOS Keychain` 跑通，知识库和学习闭环就不会卡住。
