登录与注册配置
配 Email 验证码登录 + Google OAuth + 注册白名单。避开最坑的 888888 陷阱。
Multica 支持两种登录方式:Email + 验证码(默认)和 Google OAuth(可选)。登录成功后 server 签发一个 30 天有效期的 JWT cookie。这一页讲怎么配、怎么限制谁能注册、以及自部署最容易踩的一个陷阱。
上面用到的环境变量的清单见 环境变量;token 怎么用、生命周期细节见 认证与令牌。
Email + 验证码登录怎么工作
用户在登录页输邮箱 → server 发 6 位验证码 → 用户填回 → server 验证 → 签发 JWT cookie。是标准流程。需要 Resend 作为邮件发送服务:
-
在 Resend 建账号、验证你的域名
-
创建 API key
-
设环境变量:
RESEND_API_KEY=re_xxxxxxxxxxxxxxxx RESEND_FROM_EMAIL=noreply@yourdomain.com # 必须是 Resend 已验证的域名 -
重启 server
不配 RESEND_API_KEY 的后果:server 不报错,但所有本该发出去的邮件只打到 server 的 stdout。本地开发方便(你从日志抄验证码),生产环境等于黑洞。
888888 陷阱
APP_ENV 不设为 production,任何人都能用验证码 888888 登录任何账号。
Multica 有一个开发用的主验证码(master code)888888——为了本地开发不依赖 Resend 而设的后门。判定逻辑很简单:APP_ENV != "production" 时,任何邮箱输 888888 都能通过。
生产部署必须设 APP_ENV=production。如果你用 make selfhost / docker-compose.selfhost.yml 自部署,这个值已经默认设为 production;但如果你自己从源码部署、自己写 Docker 配置、或者在 Kubernetes 里重新定义环境变量——一定要自己把 APP_ENV=production 加上。
检查你的部署是否有这个陷阱:打开登录页,输入任意邮箱请求验证码,再在验证码栏输 888888。如果能登进去 = 你的 APP_ENV 没设成 production,整个实例处于完全开放状态。
怎么配 Google OAuth
可选。不配就只有 Email + 验证码登录;配了后登录页会多出「用 Google 登录」按钮。
-
去 Google Cloud Console 创建一个 OAuth 2.0 client
-
授权的回调 URI(Authorized redirect URIs)填你的 Multica 前端地址加
/auth/callback,例如:https://multica.yourdomain.com/auth/callback -
拿到 client ID 和 client secret 后设三个环境变量:
GOOGLE_CLIENT_ID=xxxxx.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxx GOOGLE_REDIRECT_URI=https://multica.yourdomain.com/auth/callback -
重启 server。
热生效:前端通过 /api/config 运行时读这些配置——改完只要重启 server,前端不用重建镜像、不用重新部署。
回调 URI 在 Google Console 和 GOOGLE_REDIRECT_URI 两处必须完全一致,包括协议(http vs https)、尾部斜杠、端口。不一致 Google 会拒绝整个 OAuth 流程,用户看到的错误是 redirect_uri_mismatch。
怎么限制谁能注册
三层环境变量按优先级组合:
已经登录过的老用户永远可以再次登录——signup 白名单只对首次注册生效,不拦截老用户。
ALLOWED_EMAILS(最高优先级)—— 显式邮箱白名单,逗号分隔。非空时只有列表里的邮箱能注册。ALLOWED_EMAIL_DOMAINS—— 域名白名单,逗号分隔(例如company.io,partner.com)。ALLOW_SIGNUP—— 总开关,默认true。设false完全关闭注册。
三层白名单是 AND 语义,不是 OR。 很多人第一直觉是「设 ALLOWED_EMAIL_DOMAINS=company.io + ALLOW_SIGNUP=true 就是允许 company.io 和其他所有人」——不是。任何一层白名单只要设了非空值,不匹配的邮箱直接拒,ALLOW_SIGNUP=true 挡不住。
要真的「允许所有人」,所有三个环境变量都留空(或 ALLOW_SIGNUP=true)。
典型配法:
| 需求 | 配置 |
|---|---|
公司内网,只允许 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,等他们注册 + 接受邀请之后再把这条移掉。
邀请的创建和使用见 成员与权限。