编程 tinyauth:Go 认证中间件,环境变量搞定反向代理 SSO,7K Star

2026-07-11 08:43:10 +0800 CST views 7

tinyauth:Go 认证中间件,环境变量搞定反向代理 SSO

自托管玩家大概都经历过这个场景:你有十几个自托管应用(Nextcloud、Gitea、Jellyfin、Home Assistant……),每个都有自己的登录页面。你想统一管理访问权限,但一看 Authentik——Docker Compose 五个容器、PostgreSQL 数据库、Django 管理后台,光配置就花半天。

tinyauth 的定位是"你能找到的最小的认证授权服务器"。一个 Go 静态二进制,只用环境变量配置,SQLite 存储,Traefik/Caddy/Nginx/Envoy 四种反向代理通吃。15 个月内从零到 7,239 Star,说明自托管社区对"极简认证"有真实需求。

安装

# docker-compose.yml — 最小可运行配置
services:
  traefik:
    image: traefik:v3.6
    command: --api.insecure=true --providers.docker
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  whoami:
    image: traefik/whoami:latest
    labels:
      traefik.enable: true
      traefik.http.routers.whoami.rule: Host(`whoami.example.com`)
      traefik.http.routers.whoami.middlewares: tinyauth

  tinyauth:
    image: ghcr.io/steveiliop56/tinyauth:v5
    environment:
      - TINYAUTH_APPURL=https://tinyauth.example.com
      - TINYAUTH_AUTH_USERS=user:$$2a$$10$$UdLYoJ5lgPsC0RKqYH/jMua7zIn0g9kPqWmhYayJYLaZQ/FTmH2/u
    volumes:
      - ./data:/data
    labels:
      traefik.enable: true
      traefik.http.routers.tinyauth.rule: Host(`tinyauth.example.com`)
      traefik.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth/traefik

三个服务,全部在 Docker 里跑。用户访问 whoami.example.com 时,Traefik 先把请求转发给 tinyauth 做认证,认证通过才放行。不通过则 302 重定向到 tinyauth 登录页。

认证方式

本地用户

# 密码用 bcrypt 哈希
TINYAUTH_AUTH_USERS=user:$2a$10$xxx,admin:$2a$10$yyy

# 或者用文件
TINYAUTH_AUTH_USERSFILE=/data/users.txt

OAuth(Google/GitHub/GitLab/任意 OIDC)

TINYAUTH_OAUTH_PROVIDERS_google_CLIENTID=xxx
TINYAUTH_OAUTH_PROVIDERS_google_CLIENTSECRET=yyy
TINYAUTH_OAUTH_WHITELIST=gmail.com  # 限制邮箱域名

用户点击"Sign in with Google",完成 OAuth 流程后自动创建会话。OAUTH_WHITELIST 确保只有 @gmail.com 的用户能登录。

LDAP

TINYAUTH_LDAP_ADDRESS=ldaps://ldap.example.com:636
TINYAUTH_LDAP_BINDDN=cn=admin,dc=example,dc=com
TINYAUTH_LDAP_BINDPASSWORD=secret
TINYAUTH_LDAP_BASEDN=ou=users,dc=example,dc=com
TINYAUTH_LDAP_SEARCHFILTER=(uid=%s)

支持 mTLS 客户端证书认证:

TINYAUTH_LDAP_AUTHCERT=/certs/ldap-client.crt
TINYAUTH_LDAP_AUTHKEY=/certs/ldap-client.key

TOTP 二步验证

本地用户支持 TOTP 2FA(基于 pquerna/otp 库)。登录时先验证密码,再要求输入 TOTP 验证码。QR 码通过 qrterminal 在终端显示。

OIDC Provider

tinyauth 不仅是 OAuth 客户端,它自己就是一个 OIDC Provider——可以让其他应用通过 OIDC 协议向 tinyauth 认证:

# 自动生成 RSA 2048 密钥对(或指定路径)
TINYAUTH_OIDC_PRIVATEKEYPATH=/data/oidc_key
TINYAUTH_OIDC_PUBLICKEYPATH=/data/oidc_key.pub

# 注册 OIDC 客户端
TINYAUTH_OIDC_CLIENTS_myapp_CLIENTID=myapp
TINYAUTH_OIDC_CLIENTS_myapp_CLIENTSECRET=secret

OIDC 端点:

POST /api/oidc/authorize    # 授权端点
POST /api/oidc/token        # Token 端点
GET  /api/oidc/userinfo     # 用户信息端点
GET  /.well-known/openid-configuration  # 发现文档

支持 Authorization Code Flow + PKCE + Refresh Token。JWT 用 RS256 签名。

访问控制

tinyauth 的访问控制是按应用粒度的,支持两种配置方式。

方式一:环境变量

# 应用 "git" 只有 alice 和 bob 能访问
TINYAUTH_APPS_git_CONFIG_DOMAIN=git.example.com
TINYAUTH_APPS_git_USERS_ALLOW=alice,bob
TINYAUTH_APPS_git_OAUTH_GROUPS=developers
TINYAUTH_APPS_git_IP_ALLOW=10.0.0.0/8

方式二:Docker Labels

jellyfin:
  image: jellyfin/jellyfin
  labels:
    tinyauth.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth/traefik
    tinyauth.users.allow: "alice,bob"
    tinyauth.oauth.groups: "media-users"

ACL 字段

字段说明
Users.Allow/Block用户名过滤(支持 glob)
OAuth.Whitelist邮箱域名白名单
OAuth.Groups要求的 OAuth 分组
LDAP.Groups要求的 LDAP 分组
IP.Allow/Block/BypassIP/CIDR 过滤
Path.Allow/Block正则路径过滤
Response.Headers自定义响应头
Response.BasicAuth注入上游 Basic Auth

IP.Bypass 特别实用——内网 IP 可以跳过认证直接访问,外部访问则需要登录。

Forward Auth 原理

tinyauth 的核心机制是 Forward Auth(转发认证)。不是所有请求都经过 tinyauth,而是反向代理在每个请求前先问 tinyauth:"这个用户能不能访问?"

浏览器 → Traefik → tinyauth/api/auth/traefik
              ↓                ↓
          检查 Cookie      验证会话
              ↓                ↓
          已认证 → 放行    未认证 → 302 到登录页
              ↓
          转发到后端应用

四种代理适配:

代理认证方式读取的 Header
TraefikForwardAuthX-Forwarded-Host/URI/Proto
CaddyForwardAuth同 Traefik
EnvoyExtAuthzX-Forwarded-Proto + query path
NginxAuthRequestX-Original-URL

认证通过后,tinyauth 设置这些 Header 传给后端应用:

Remote-User: alice
Remote-Name: Alice Smith
Remote-Email: alice@example.com
Remote-Groups: developers,admins

后端应用可以读取这些 Header 获取用户信息,不需要自己实现认证。

Go 实现的技术亮点

Gin 框架 + 中间件链

tinyauth 使用 Gin 作为 HTTP 框架,中间件链清晰:

请求 → zerolog 中间件(日志)→ context 中间件(会话验证)→ 路由处理器

context_middleware.go 是认证的核心:

  • 检查会话 Cookie(默认 24h 有效)
  • 如果 TOTP 待验证,限制访问
  • OAuth 用户验证邮箱域名
  • LDAP 用户获取分组信息(缓存 900s)

sqlc + golang-migrate

SQL 层面使用 sqlc 生成类型安全的 Go 代码:

-- sql/session_queries.sql
-- name: GetSession :one
SELECT * FROM sessions WHERE uuid = ? AND expiry > strftime('%s','now');
// 自动生成
func (q *Queries) GetSession(ctx context.Context, uuid string) (Session, error)

数据库迁移用 golang-migrate,SQLite schema 管理规范化。

pure Go SQLite

// go.mod
modernc.org/sqlite v1.48.2

纯 Go 实现,不需要 CGO。CGO_ENABLED=0 编译出的静态二进制可以在任何 Linux 上运行,不依赖 glibc。SQLite 存储会话、OIDC codes/tokens、用户信息——所有数据都在一个文件里。

Docker SDK 读取 Labels

tinyauth 使用 Docker SDK(docker/docker)读取同一 Docker 网络上的容器 Labels:

// 自动发现带 tinyauth.* labels 的容器
// 不需要手动配置每个应用的域名

这让访问控制的配置贴近应用本身——在应用的 docker-compose.yml 里写 labels 就行。

总结

tinyauth 用极简的方式解决了自托管场景的统一认证问题:

  • 一个静态二进制,零外部依赖
  • 环境变量 + Docker Labels 双配置
  • 本地/OAuth/LDAP/TOTP/OIDC 全支持
  • 四种反代通吃,Forward Auth 标准机制

如果你也被十几个自托管应用的登录页折磨过,tinyauth 值得一试。

GitHub:https://github.com/steveiliop56/tinyauth

推荐文章

前端开发中常用的设计模式
2024-11-19 07:38:07 +0800 CST
120个实用CSS技巧汇总合集
2025-06-23 13:19:55 +0800 CST
SpaceX 600亿美元收购Cursor(节选)
2026-06-22 03:29:52 +0800 CST
Vue3中如何处理状态管理?
2024-11-17 07:13:45 +0800 CST
手机导航效果
2024-11-19 07:53:16 +0800 CST
Shell 里给变量赋值为多行文本
2024-11-18 20:25:45 +0800 CST
Vue3中的组件通信方式有哪些?
2024-11-17 04:17:57 +0800 CST
程序员茄子在线接单