mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-29 06:28:23 +02:00
* fix: gate dev verification code behind explicit env * docs: fold dev verification code into env table * docs: clarify fixed verification code opt-in --------- Co-authored-by: Eve <eve@multica.ai>
129 lines
6.2 KiB
Plaintext
129 lines
6.2 KiB
Plaintext
---
|
||
title: 登录与注册配置
|
||
description: 配 Email 验证码登录、Google OAuth、注册白名单和本地测试验证码。
|
||
---
|
||
|
||
import { Callout } from "fumadocs-ui/components/callout";
|
||
import { Mermaid } from "@/components/mermaid";
|
||
|
||
Multica 支持两种登录方式:**Email + 验证码**(默认)和 **Google OAuth**(可选)。登录成功后 server 签发一个 30 天有效期的 JWT cookie。这一页讲怎么配、怎么限制谁能注册、以及本地测试验证码怎么安全使用。
|
||
|
||
上面用到的环境变量的清单见 [环境变量](/environment-variables);token 怎么用、生命周期细节见 [认证与令牌](/auth-tokens)。
|
||
|
||
## Email + 验证码登录怎么工作
|
||
|
||
用户在登录页输邮箱 → server 发 6 位验证码 → 用户填回 → server 验证 → 签发 JWT cookie。是标准流程。需要 [Resend](https://resend.com/) 作为邮件发送服务:
|
||
|
||
1. 在 Resend 建账号、验证你的域名
|
||
2. 创建 API key
|
||
3. 设环境变量:
|
||
|
||
```bash
|
||
RESEND_API_KEY=re_xxxxxxxxxxxxxxxx
|
||
RESEND_FROM_EMAIL=noreply@yourdomain.com # 必须是 Resend 已验证的域名
|
||
```
|
||
|
||
4. 重启 server
|
||
|
||
**不配 `RESEND_API_KEY` 的后果**:server 不报错,但**所有本该发出去的邮件只打到 server 的 stdout**。本地开发方便(你从日志抄验证码),生产环境等于黑洞。
|
||
|
||
## 固定本地测试验证码
|
||
|
||
<Callout type="warning">
|
||
**不要在公网可访问实例上启用固定验证码。**
|
||
|
||
旧版「非 production 默认接受 `888888`」的行为已经移除。除非你显式配置,否则输入 `888888` 会和普通错误验证码一样被拒绝。
|
||
|
||
不配 Resend 的本地开发,应使用 server 日志里打印的随机验证码。如果你需要确定性的本地/私有自动化测试,可以把 `MULTICA_DEV_VERIFICATION_CODE` 设成一个 6 位数字,比如 `888888`,并保持 `APP_ENV` 为非 production:
|
||
|
||
```bash
|
||
APP_ENV=development
|
||
MULTICA_DEV_VERIFICATION_CODE=888888
|
||
```
|
||
|
||
`APP_ENV=production` 时这个快捷码会被忽略。
|
||
</Callout>
|
||
|
||
生产部署应保持 `MULTICA_DEV_VERIFICATION_CODE` 为空,并设置 `APP_ENV=production`。如果你用 `make selfhost` / `docker-compose.selfhost.yml` 自部署,`APP_ENV` 默认就是 `production`。
|
||
|
||
## 怎么配 Google OAuth
|
||
|
||
可选。不配就只有 Email + 验证码登录;配了后登录页会多出「用 Google 登录」按钮。
|
||
|
||
1. 去 [Google Cloud Console](https://console.cloud.google.com/) 创建一个 OAuth 2.0 client
|
||
2. **授权的回调 URI**(Authorized redirect URIs)填你的 Multica 前端地址加 `/auth/callback`,例如:
|
||
|
||
```text
|
||
https://multica.yourdomain.com/auth/callback
|
||
```
|
||
|
||
3. 拿到 client ID 和 client secret 后设三个环境变量:
|
||
|
||
```bash
|
||
GOOGLE_CLIENT_ID=xxxxx.apps.googleusercontent.com
|
||
GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxx
|
||
GOOGLE_REDIRECT_URI=https://multica.yourdomain.com/auth/callback
|
||
```
|
||
|
||
4. 重启 server。
|
||
|
||
**热生效**:前端通过 `/api/config` 运行时读这些配置——改完只要重启 server,前端不用重建镜像、不用重新部署。
|
||
|
||
<Callout type="warning">
|
||
**回调 URI 在 Google Console 和 `GOOGLE_REDIRECT_URI` 两处必须完全一致**,包括协议(`http` vs `https`)、尾部斜杠、端口。不一致 Google 会拒绝整个 OAuth 流程,用户看到的错误是 `redirect_uri_mismatch`。
|
||
</Callout>
|
||
|
||
## 怎么限制谁能注册
|
||
|
||
三层环境变量按优先级组合:
|
||
|
||
<Mermaid chart={`
|
||
graph TD
|
||
Start[新用户首次登录] --> A{email 在<br/>ALLOWED_EMAILS 里?}
|
||
A -- 是 --> Allow[允许注册]
|
||
A -- 否 --> B{domain 在<br/>ALLOWED_EMAIL_DOMAINS 里?}
|
||
B -- 是 --> Allow
|
||
B -- 否 --> C{任一白名单<br/>非空?}
|
||
C -- 是 --> Block[拒绝]
|
||
C -- 否 --> D{ALLOW_SIGNUP<br/>= true?}
|
||
D -- 是 --> Allow
|
||
D -- 否 --> Block
|
||
`} />
|
||
|
||
**已经登录过的老用户永远可以再次登录**——signup 白名单只对**首次注册**生效,不拦截老用户。
|
||
|
||
- **`ALLOWED_EMAILS`**(最高优先级)—— 显式邮箱白名单,逗号分隔。**非空时只有列表里的邮箱能注册**。
|
||
- **`ALLOWED_EMAIL_DOMAINS`**—— 域名白名单,逗号分隔(例如 `company.io,partner.com`)。
|
||
- **`ALLOW_SIGNUP`** —— 总开关,默认 `true`。设 `false` 完全关闭注册。
|
||
|
||
<Callout type="warning">
|
||
**三层白名单是 AND 语义,不是 OR。** 很多人第一直觉是「设 `ALLOWED_EMAIL_DOMAINS=company.io` + `ALLOW_SIGNUP=true` 就是允许 company.io 和其他所有人」——**不是**。任何一层白名单只要设了非空值,**不匹配的邮箱直接拒**,`ALLOW_SIGNUP=true` 挡不住。
|
||
|
||
要真的「允许所有人」,所有三个环境变量都留空(或 `ALLOW_SIGNUP=true`)。
|
||
</Callout>
|
||
|
||
**典型配法**:
|
||
|
||
| 需求 | 配置 |
|
||
|---|---|
|
||
| 公司内网,只允许 `company.io` 员工 | `ALLOWED_EMAIL_DOMAINS=company.io` |
|
||
| 公司内网 + 几个外部合作者 | `ALLOWED_EMAIL_DOMAINS=company.io` + 合作者个人邮箱加到 `ALLOWED_EMAILS` |
|
||
| 完全关闭自助注册,只能邀请 | `ALLOW_SIGNUP=false` |
|
||
| 开放注册(不推荐生产用)| 三个都留空 |
|
||
|
||
## 关了注册还能邀请人进来吗
|
||
|
||
**只对已经有 Multica 账号的人能**。接受邀请那一步不检查 signup 白名单——如果对方已经注册过(比如在别的工作区),他们点链接登录就能直接接受。
|
||
|
||
**但还没注册过的人,邀请救不了他们**。他们接受邀请前必须先登录,登录的第一步(发验证码)会过 signup 白名单检查。如果你 `ALLOW_SIGNUP=false`、或他们的邮箱不在 `ALLOWED_EMAILS` / `ALLOWED_EMAIL_DOMAINS` 里,他们**没法完成注册**,也就没法接受邀请。
|
||
|
||
要邀请一个还没注册的外部协作者:临时把他们的邮箱加到 `ALLOWED_EMAILS`,等他们注册 + 接受邀请之后再把这条移掉。
|
||
|
||
邀请的创建和使用见 [成员与权限](/members-roles)。
|
||
|
||
## 下一步
|
||
|
||
- [环境变量](/environment-variables) —— 这一页用到的环境变量完整定义
|
||
- [认证与令牌](/auth-tokens) —— JWT / PAT / Daemon Token 的分类和使用
|
||
- [故障排查](/troubleshooting) —— 验证码收不到、OAuth 报 `redirect_uri_mismatch`、注册被拒的常见排查
|