SnapOtter OIDC/SSO配置教程:3步接入Google、GitHub与Okta单点登录
【免费下载链接】SnapOtterOpen-source, self-hosted file-processing tool. Convert, compress, OCR, transcribe & run local AI across image, video, audio, PDF & documents, via UI, REST API & pipelines. Your files never leave your network.项目地址: https://gitcode.com/gh_mirrors/st/SnapOtter
SnapOtter是一款开源、自托管的文件处理工具,支持转换、压缩、OCR、转写和运行本地 AI,而它的OIDC 单点登录(SSO)功能可以让你用 Google、GitHub 或 Okta 账户直接登录,彻底告别为每个用户维护密码的麻烦。本教程带你3 步完成配置,全程无需修改代码。
为什么要给文件处理工具加 SSO
团队共享一台 SnapOtter 时,本地账户密码意味着:要手动开号、手动分配权限、离职后手动清理。接入 OIDC/SSO 后:
- ✅ 成员用公司 IdP(Google Workspace、GitHub、Okta 等)一键登录,零密码下发
- ✅ 新用户登录时自动创建账号(默认开启),并分配默认角色
- ✅ 可把 IdP 身份与已有本地账号自动关联,老用户无感迁移
- ✅ 登录日志、MFA 策略与本地登录完全一致,审计不缺位
SnapOtter 的 SSO 由两个核心模块实现:OIDC 走 plugins/oidc.ts,SAML(企业版)走 plugins/saml.ts。两者共享同一个用户解析器 lib/external-auth-resolver.ts,所以行为一致。
准备工作:先确认 3 件事
在动手前,确认你的部署满足以下条件:
- 已部署 SnapOtter:通过 Docker Compose 部署(参考 docker-compose.yml),或源码部署均可
- 有可访问的
EXTERNAL_URL:即浏览器访问 SnapOtter 的完整地址(如https://files.example.com)。启用 SSO 时该变量必填,且路径必须与BASE_PATH一致,否则登录会因 state 校验失败 - 有 IdP 管理权限:能在 Google Cloud Console / GitHub / Okta 创建应用
第 1 步:在身份提供商(IdP)创建 OIDC 应用
三种主流 IdP 的操作路径都类似:创建一个OIDC/OAuth 客户端,拿到 Issuer、Client ID、Client Secret,并登记回调地址。
Google Workspace / Google Cloud
- 进入 Google Cloud Console → 凭据 → 创建"OAuth 客户端",应用类型选Web
- 在"已获授权的重定向 URI"中填入(注意必须是 SnapOtter 的完整公网地址 + 固定路径):
https://你的域名/api/auth/oidc/callback - 记下 Client ID 与 Client Secret;Issuer URL 固定为
https://accounts.google.com - 确认 Google 应用已申请
openid、profile、email这三个 scope 对应的数据访问
GitHub
- 进入 GitHub → Settings → Developer settings → OAuth Apps(或 OAuth Apps 新入口)创建应用
- 回调地址同样填:
https://你的域名/api/auth/oidc/callback - Issuer URL 为
https://github.com/login/oauth/openid
Okta
- 控制台 → Applications → Add Application → OIDC
- Sign-in URL 填
https://你的域名,Allowed POST redirect URIs 填https://你的域名/api/auth/oidc/callback - Issuer URL 为你的租户地址:
https://你的租户名.okta.com
💡 三个 IdP 的共同点:回调路径永远是
/api/auth/oidc/callback,由 SnapOtter 自动发现元数据(discovery)完成其余握手,你不需要填授权端点、令牌端点等细节。
第 2 步:配置 SnapOtter 环境变量
拿到 IdP 凭证后,编辑 Docker Compose 配置。docker/docker-compose.yml 中已内置了完整的 OIDC 配置注释块(约第 67–87 行),直接取消注释并填值即可。核心变量如下:
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
OIDC_ENABLED | ✅ | false | 设为true开启 |
OIDC_ISSUER_URL | ✅ | — | IdP 发现地址(上一步的值) |
OIDC_CLIENT_ID | ✅ | — | 应用 Client ID |
OIDC_CLIENT_SECRET | ✅ | — | 应用 Client Secret |
EXTERNAL_URL | ✅ | — | 公网访问地址,如https://files.example.com |
OIDC_SCOPES | ⬜ | openid profile email | 请求的权限范围 |
OIDC_AUTO_CREATE_USERS | ⬜ | true | 首次登录自动建号 |
OIDC_DEFAULT_ROLE | ⬜ | user | 自动建号的角色 |
OIDC_AUTO_LINK_USERS | ⬜ | false | 按邮箱自动关联本地老账号 |
OIDC_PROVIDER_NAME | ⬜ | — | 登录页按钮显示的名称 |
OIDC_USERNAME_CLAIM | ⬜ | preferred_username | 取哪个声明作为用户名 |
OIDC_CLOCK_TOLERANCE | ⬜ | 30 | 时钟容差(秒),解决服务器时间偏差 |
这些变量的完整定义与启动校验逻辑见 lib/env.ts。
两个值得注意的细节:
- 密钥走文件更安全:Compose 注释中还提供了
OIDC_CLIENT_SECRET_FILE=/run/secrets/oidc_secret,启动脚本 entrypoint.sh 支持从文件读取密钥,避免明文写在 YAML 里 - 用户名推导链:登录成功后,SnapOtter 按「指定 claim →
preferred_username→ 邮箱前缀 → 姓名 → subject」的顺序推导用户名(逻辑在 plugins/oidc.ts 的deriveUsername),无需你手工维护映射表
第 3 步:重启并验证登录
docker compose up -d --force-recreate打开https://你的域名/login,你会看到:
- 登录页出现 IdP 的登录按钮(按钮名由
OIDC_PROVIDER_NAME决定) - 点击后跳转到 IdP 登录页,授权后自动回跳
- 用户自动创建并进入主界面,角色为
OIDC_DEFAULT_ROLE
验证排障清单:
| 现象 | 原因与处理 |
|---|---|
| 登录页无 SSO 按钮 | OIDC_ENABLED未设为true,或未重启容器 |
oidc_provider_unreachable | Issuer URL 不可达,检查 DNS / 防火墙 / 证书 |
oidc_session_expired | EXTERNAL_URL与BASE_PATH路径不一致,或 cookie 被浏览器拦截(需 HTTPS) |
oidc_user_not_authorized | OIDC_AUTO_CREATE_USERS=false且该 IdP 身份未绑定本地账号 |
| IdP 报重定向 URI 不匹配 | 回调地址少了协议头或末尾斜杠,必须是https://域名/api/auth/oidc/callback |
| 时间相关校验失败 | 调大OIDC_CLOCK_TOLERANCE |
进阶:Okta 等企业 IdP 的 SAML 接入
如果你的组织只发 SAML 断言(如 Okta、Azure AD 的传统配置),SnapOtter 也提供 SAML 2.0 支持(企业版许可,saml_sso功能开关)。与 OIDC 的关键区别:
- 需要额外提供 IdP 证书与 SSO URL:
SAML_IDP_CERTIFICATE、SAML_IDP_SSO_URL(均为必填) - IdP 配置时需要导入 SnapOtter 的 SP 元数据:直接访问
https://你的域名/api/auth/saml/metadata获取 XML - ACS 回调地址:
https://你的域名/api/auth/saml/callback - 用户名/邮箱取自 SAML 断言属性:
SAML_USERNAME_ATTRIBUTE与SAML_EMAIL_ATTRIBUTE(默认email)
SAML 的完整握手与防重放校验(InResponseTo绑定)实现在 plugins/saml.ts,基于 Redis 缓存请求 ID,多实例部署也安全。
常见问题速查
Q:SSO 登录还能用密码登录吗?可以,两种方式并存,登录页同时显示本地登录与 SSO 按钮。
Q:本地老账号怎么绑到 IdP?开启OIDC_AUTO_LINK_USERS=true后,IdP 邮箱与本地账号邮箱一致时自动关联;也可由管理员在用户管理中手工绑定。
Q:登出会同步登出 IdP 吗?会。如果 IdP 元数据提供了end_session_endpoint,SnapOtter 会在登出时发起 RP 发起的登出(见 plugins/oidc.ts 的getOidcEndSessionEndpoint)。
Q:和 MFA 是什么关系?完全兼容。若用户已启用 TOTP,OIDC/SAML 登录成功后仍会按 MFA 策略弹出二次验证,安全策略不因 SSO 而绕过。
参考资料
- 环境变量完整定义:apps/api/src/lib/env.ts
- OIDC 登录流程源码:apps/api/src/plugins/oidc.ts
- SAML 登录流程源码:apps/api/src/plugins/saml.ts
- 用户解析与自动建号:apps/api/src/lib/external-auth-resolver.ts
- Docker 部署配置(含 OIDC 注释块):docker/docker-compose.yml
- 会话与登出逻辑:apps/api/src/plugins/auth.ts
按本文 3 步操作,大约 10 分钟即可让你的 SnapOtter 接入企业级单点登录——文件不出内网,登录交给 IdP,管理从此省心 🎉
【免费下载链接】SnapOtterOpen-source, self-hosted file-processing tool. Convert, compress, OCR, transcribe & run local AI across image, video, audio, PDF & documents, via UI, REST API & pipelines. Your files never leave your network.项目地址: https://gitcode.com/gh_mirrors/st/SnapOtter
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考