# GitHub / Gitea / Google / Microsoft / LINUX DO 登录：开发与生产环境测试指南

本文说明如何在**本地开发**与**生产环境**中配置、测试并验证萌芽统一账户的第三方 OAuth 登录（GitHub、自建 Gitea、[Google 账号](https://console.cloud.google.com/)、[Microsoft / Entra ID](https://entra.microsoft.com/)、以及 [LINUX DO Connect](https://connect.linux.do)）。

---

## 一、共同概念

### 1.1 两次「地址」要分清


| 角色                   | 说明                                                                | 典型开发值                             | 典型生产值                          |
| -------------------- | ----------------------------------------------------------------- | --------------------------------- | ------------------------------ |
| **API 根地址**          | 浏览器与 SproutGate 后端通信的基址；OAuth **回调**由后端路径承担                       | `http://localhost:8080`           | `https://auth.api.example.com` |
| **前端回跳 `return_to`** | 用户授权完成后，后端把浏览器重定向到该地址，并在 **URL fragment（# 后）** 写入 `oauth_token` 等 | `http://localhost:5173/`（Vite 默认） | `https://你的前端站/`               |
| **允许的回跳前缀**          | 管理后台「第三方登录」里配置的 **白名单**；`return_to` 必须以其中某一项为前缀，否则拒绝              | 需包含开发用前端根                         | 需包含生产前端根                       |


### 1.2 在各 IdP 里要填的「回调 / Redirect URI」

OAuth 应用里登记的 **Redirect URI** 必须与后端实际对外地址一致（协议、主机、端口、路径一字不差）：

- GitHub：  
`{API根}/api/auth/oauth/github/callback`
- Gitea：  
`{API根}/api/auth/oauth/gitea/callback`
- Google（Google Cloud「OAuth 2.0 客户端 ID」，类型为 **Web 应用** 时的「已获授权的重定向 URI」）：  
`{API根}/api/auth/oauth/google/callback`
- Microsoft / Azure / Entra（**应用注册** → 身份验证 → 添加平台 **Web** 的「重定向 URI」）：  
`{API根}/api/auth/oauth/microsoft/callback`  
  本服务使用 **v2.0 授权终结点**；租户在管理后台为 **Microsoft 租户** 字段，默认 `common`（多租户 + 个人 Microsoft 账号）。若你只需单一组织目录，可改为**具体租户 ID**。
- LINUX DO（Connect 应用接入）：  
`{API根}/api/auth/oauth/linuxdo/callback`  
与你在 [应用接入](https://connect.linux.do) 中填写的回调一致即可（开发时可为 `http://localhost:8080/...`）。

开发时 `{API根}` 多为 `http://localhost:8080`；生产时为 `https://你的 API 域名`（无尾部斜杠）。

### 1.3 后端环境变量（与部署相关）


| 变量                                                                       | 作用                                                                                                                                                                                     |
| ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PUBLIC_API_BASE`                                                        | **建议生产必设**。值为 **纯 API 根**（无路径），如 `https://auth.api.example.com`。用于拼 OAuth `redirect_uri`。本地若访问 API 用 `http://localhost:8080`，可设 `PUBLIC_API_BASE=http://localhost:8080`，与浏览器访问后端的地址一致。 |
| `GITHUB_CLIENT_SECRET` / `GITEA_CLIENT_SECRET` / `GOOGLE_CLIENT_SECRET` / `MICROSOFT_CLIENT_SECRET` / `LINUXDO_CLIENT_SECRET` | 可选；若设置，会覆盖数据库里保存的对应 Secret，便于不把 Secret 写进库。                                                                                                                                              |
| `PORT`                                                                   | 后端监听端口，默认 `8080`。                                                                                                                                                                      |


---

## 二、开发环境（本机）

### 2.1 默认假设

- 后端：`http://localhost:8080`（`go run .` 或 `sproutgate.bat dev`）
- 前端：`http://localhost:5173`（`npm run dev`）
- 前端已配置 `VITE_API_BASE=http://localhost:8080`（或留空走开发默认）

### 2.2 在 GitHub 创建 OAuth App

1. 打开 GitHub → **Settings** → **Developer settings** → **OAuth Apps** → **New OAuth App**（或 Organization 下创建）。
2. 填写示例：
  - **Application name**：任意，如 `SproutGate Dev`
  - **Homepage URL**：`http://localhost:5173`
  - **Authorization callback URL**：  
  `http://localhost:8080/api/auth/oauth/github/callback`
3. 创建后记录 **Client ID**，生成 **Client secrets** 并复制保存（只显示一次）。

GitHub 允许使用 `http://localhost` 作为回调，无需公网。

### 2.3 在 LINUX DO Connect 创建应用

1. 打开 [https://connect.linux.do](https://connect.linux.do)（需登录），侧栏 **应用接入** → 新建接入。
2. **回调地址** 填 `http://localhost:8080/api/auth/oauth/linuxdo/callback`（生产改为 `https://{API域名}/api/auth/oauth/linuxdo/callback`）。
3. 保存后记录 **Client ID**、**Client Secret**；管理后台「LINUX DO Connect 根地址」通常填 `https://connect.linux.do`（与官方端点一致即可）。

### 2.4 在 Gitea 创建 OAuth2 应用

1. 登录你的 Gitea（如 `https://git.shumengya.top`）→ **站点管理** 或 **用户设置** 中的 **Applications** / **OAuth2**，创建新应用（不同版本菜单位置略有差异）。
2. **Redirect URI**（重定向 URI）：
  `http://localhost:8080/api/auth/oauth/gitea/callback`
3. 记录 **Client ID**、**Client Secret**，勾选所需权限（至少能读用户资料，一般 `read:user` 或界面勾「读取用户信息」类选项）。

### 2.4a 在 Google Cloud 创建 OAuth 2.0 客户端（可选）

1. 打开 [Google Cloud Console](https://console.cloud.google.com/)，选择或创建项目 → **API 和服务** → **OAuth 同意屏幕**（先配置为测试/内部/公开视需求）。
2. **凭据** → **创建凭据** → **OAuth 客户端 ID** → 应用类型选 **Web 应用**。
3. **已获授权的重定向 URI** 填 `http://localhost:8080/api/auth/oauth/google/callback`（生产改为 `https://{API域名}/api/auth/oauth/google/callback`）。
4. 记录 **客户端 ID**、**客户端密钥**；在 SproutGate 管理后台「第三方登录」中勾选 **Google** 并填入。

### 2.4b 在 Microsoft Entra（原 Azure AD）应用注册（可选）

1. 打开 [Microsoft Entra 管理中心](https://entra.microsoft.com/) → **应用注册** → **新注册**。
2. 支持的帐户类型中，若与后台 **Microsoft 租户** 填 `common` 一致，通常选「**任何组织目录中的帐户和个人 Microsoft 帐户**」。
3. **身份验证** → 添加平台 **Web** → **重定向 URI** 填 `http://localhost:8080/api/auth/oauth/microsoft/callback`（生产用 HTTPS 与真实 API 域）。
4. 在 **证书和密码** 中创建 **客户端密码**，并记录**应用程序(客户端) ID** 与 secret；管理后台 **Microsoft 租户** 可填 `common` 或你的目录租户 ID（单租户时便于限制登录范围）。

### 2.5 在 SproutGate 管理后台配置

1. 打开管理页，填写 **管理员 Token**，进入 **第三方登录**。
2. 按需勾选 **GitHub** / **Gitea** / **Google** / **Microsoft** / **LINUX DO 登录**。
3. 分别填入各平台的 **Client ID** 与 **Client Secret**；Microsoft 另填 **Microsoft 租户**（默认 `common`）；LINUX DO 另需确认 **Connect 根地址**（默认 `https://connect.linux.do`）。
4. **Gitea 根地址**：如 `https://git.shumengya.top`（无尾斜杠也可，保存时会规范化）。
5. **允许的回跳地址**：至少包含（每行一个，**建议带尾斜杠**）：
  - `http://localhost:5173/`
  - 若用 `127.0.0.1` 打开前端，再加一行：  
  `http://127.0.0.1:5173/`
6. **需邀请时仍允许 OAuth 新用户**：若你开启了「强制邀请码」自助注册，又想用 OAuth **直接注册**新账号，需勾选此项；否则邀请制下 OAuth 只能登录**已绑定**的账号。
7. 保存。

### 2.6 本地设置 `PUBLIC_API_BASE`（推荐）

使后端生成的 OAuth `redirect_uri` 与你在各平台应用里填的完全一致：

**Windows PowerShell（当前终端）**

```powershell
$env:PUBLIC_API_BASE = "http://localhost:8080"
```

**或在启动脚本里** 写死上述一行再启动后端。

然后重启后端，再测登录。

### 2.7 验证步骤（开发）

1. 打开 `http://localhost:5173`，**退出**当前登录（如有）。
2. 在登录界面应看到已启用的第三方按钮（**GitHub**、**Gitea**、**谷歌**、**微软**、**LINUX DO** 等，仅当对应「启用」已打开）。
3. 点击 **GitHub**：应跳转到 GitHub 授权页，授权后回到 `http://localhost:5173/#oauth_token=...`（地址栏 hash 中有 token），页面应显示已登录。
4. 退出后测 **Gitea** / **Google** / **Microsoft** / **LINUX DO**，流程同上（LINUX DO 会先到 `connect.linux.do` 授权页）。
5. **绑定**：先普通登录，进入用户中心 → **第三方账号** → **绑定**，应跳转到对应平台，返回后应显示「已绑定」。
6. **解绑**：点「解绑」，确认后状态应更新。

若返回后 URL 带 `#oauth_error=1`，查看 `oauth_error_description` 片段内容（多为白名单、`redirect_uri` 不匹配、或策略禁止注册等）。

---

## 三、生产环境

### 3.1 前置条件

- API 对外为 **HTTPS**（GitHub 生产回调通常要求 HTTPS；本地 localhost 除外）。
- 用户浏览器能访问：**前端域名**、**API 域名**、**Gitea 域名**（若用 Gitea 登录）。

### 3.2 在 GitHub 生产 OAuth App

1. 新建或使用独立 **Production** OAuth App（勿与开发混用同一回调，易错）。
2. **Authorization callback URL** 填：
  `https://{你的API域名}/api/auth/oauth/github/callback`  
   例如：`https://auth.api.shumengya.top/api/auth/oauth/github/callback`
3. 记录 Client ID / Secret。

### 3.3 在 Gitea 生产 OAuth 应用

1. **Redirect URI**：
  `https://{你的API域名}/api/auth/oauth/gitea/callback`
2. 记录 Client ID / Secret。

### 3.4 服务器环境变量

示例（按你的实际域名修改）：

```bash
export PUBLIC_API_BASE="https://auth.api.shumengya.top"
export GITHUB_CLIENT_SECRET="..."     # 可选
export GITEA_CLIENT_SECRET="..."      # 可选
export GOOGLE_CLIENT_SECRET="..."     # 可选
export MICROSOFT_CLIENT_SECRET="..."  # 可选
```

确保反向代理（Nginx/Caddy 等）转发的 **Host** / **X-Forwarded-Proto** 正确，否则未设 `PUBLIC_API_BASE` 时，程序可能错误拼出 `http` 或错误主机，导致与 GitHub/Gitea 登记的回调不一致。

### 3.5 前端

- 生产构建时设置 `VITE_API_BASE=https://{你的API域名}`（与浏览器实际请求后端的地址一致，无多余斜杠）。

### 3.6 管理后台

在 **允许的回跳地址** 中加入生产前端的根地址，例如：

```text
https://user.shumengya.top/
```

（具体以你实际用户访问的「用户中心 / 登录页」域名为准，**须带尾斜杠**，与代码里 `getOAuthReturnTo()` 生成的前缀匹配。）

保存各平台的 Client ID；Secret 可用环境变量注入，界面里可留空以保留原值。

### 3.7 验证步骤（生产）

与 **2.6** 相同，只是把 `http://localhost:5173` 换成线上前端地址，并确认：

- 授权完成后地址栏出现 `oauth_token` 或绑定成功后的 `oauth_bound`；
- 新用户（未注册过）在允许策略下可完成首次 OAuth 注册（视「邀请码」与「需邀请时仍允许 OAuth 新用户」组合而定）。

---

## 四、常见问题


| 现象                                           | 可能原因                                          | 处理                                                        |
| -------------------------------------------- | --------------------------------------------- | --------------------------------------------------------- |
| GitHub 提示 `redirect_uri` 不匹配                 | 回调 URL 与 OAuth 应用配置不一致，或 `PUBLIC_API_BASE` 错误 | 对齐三处：GitHub 后台、`PUBLIC_API_BASE`、实际访问 API 的协议与主机          |
| 回到前端后 `#oauth_error`，描述含 `invalid return_to` | 前端 `return_to` 不在白名单                          | 在管理后台增加该前端的 **根地址前缀**（含 `https://` 与尾 `/`）                |
| 邀请制下无法 OAuth 新用户                             | 策略限制                                          | 开启「需邀请时仍允许 OAuth 新用户」，或关闭「强制邀请码」，或先用邮箱+邀请码注册再绑定           |
| Gitea 授权后失败                                  | Gitea 实例不能访问、或 Token 请求失败                     | 检查服务器能否访问 Gitea；Client ID/Secret；Gitea OAuth 应用回调是否填对     |
| LINUX DO 提示 scope 或 `userinfo_failed`        | 应用权限、或 `/api/user` 返回非 200                    | 确认 Connect 应用已同意；本服务使用 scope `read:user`；可查看后端日志中 HTTP 状态 |
| 本地能行、生产不行                                    | 多为 HTTPS、反代头、`PUBLIC_API_BASE`、白名单未含生产前端      | 逐项对照第二节、第三节                                               |


---

## 五、快速检查清单

**开发**

- `http://localhost:8080/api/health` 可访问  
- 各平台回调填 `http://localhost:8080/api/auth/oauth/{github|gitea|google|microsoft|linuxdo}/callback`  
- 管理后台白名单含 `http://localhost:5173/`（及实际使用的前端 origin）  
- 已设 `PUBLIC_API_BASE=http://localhost:8080`（推荐）  
- `VITE_API_BASE` 指向本机 API

**生产**

- API 与前端均为 HTTPS（或符合你安全策略）  
- OAuth 应用回调为 `https://{API}/api/auth/oauth/.../callback`  
- `PUBLIC_API_BASE` 与对外 API 一致  
- 白名单含生产前端根 URL（尾斜杠）  
- 前端 `VITE_API_BASE` 为生产 API

按上述配置后，即可在对应环境完成 GitHub、Gitea、Google、Microsoft、LINUX DO 登录及绑定验证。