
使用TinyAuth和Traefik实现简单的认证代理

Skyone
科技爱好者
你是否遇到过需要为不支持认证的服务添加认证的情况?TinyAuth 是一个轻量级的认证代理,可以帮助你为这些服务添加基本的认证。本文将介绍如何使用 TinyAuth 和 Traefik 实现简单的认证代理。
TinyAuth 支持包括 GitHub OAuth、简单密码认证在内的多种认证方式,这里我使用 Pocket ID 为例。
准备工作
在开始之前,请确保你已经正确配置了 Traefik,并且可以通过 Traefik 访问你的服务。如果你还没有配置 Traefik,可以参考 使用 Traefik 作为 Docker 的反向代理 进行配置。
此外,我这里使用 Pocket ID 作为认证方式,你可以自行选择其他认证方式,参考 TinyAuth 的文档。
现在假设有一个 echo
服务,需要添加认证,其域名是 echo.skyone.dev
,我们需要在 .skyone.dev
下的任意子域名上部署 TinyAuth(与 echo
服务的域名在同一个域下),这里我使用 auth.skyone.dev
。
在 Pocket ID 中注册应用
首先,你需要访问 Pocket ID 的管理面板,在 OIDC Clients 标签页中点击 Add OIDC Client。会出现一个新菜单,提示你提供一些信息。我们只需要设置其中的两个字段:
- Client ID: 这是你的应用的唯一标识符,可以随意设置。
- Redirect URI: 这是 TinyAuth 的回调地址,格式为
https://tinyauth.domain/api/oauth/callback/generic
。例如,我的回调地址是https://auth.skyone.dev/api/oauth/callback/generic
。
其他的选项都可以保持默认。创建完成后,你会得到一个 Client ID 和 Client Secret,这两个值稍后会用到。
部署 TinyAuth
接下来,我们需要配置 TinyAuth。首先,创建一个名为 tinyauth
的 Docker Compose 文件,内容如下:
name: tinyauth
services:
tinyauth:
image: ghcr.io/steveiliop56/tinyauth:v3
container_name: tinyauth
restart: unless-stopped
networks:
- proxy
env_file:
- docker.env
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.tinyauth.rule=Host(`tinyauth.skyone.dev`)"
- "traefik.http.routers.tinyauth.entrypoints=websecure"
- "traefik.http.routers.tinyauth.service=tinyauth"
- "traefik.http.services.tinyauth.loadBalancer.server.port=3000"
- "traefik.http.middlewares.tinyauth.forwardAuth.address=http://tinyauth:3000/api/auth/traefik"
networks:
proxy:
external: true
这里需要修改的部分是 tinyauth.skyone.dev
,将其替换为你自己的域名。
这里 labels 的最后一行为 Traefik 指定了一个中间件 tinyauth
,这个中间件会在请求到达 tinyauth
服务之前进行认证,http://tinyauth:3000
是 TinyAuth 在容器内部的地址。
接下来,创建一个名为 docker.env
的环境变量文件,内容如下:
# --- Required Environment Variables ---
TINY_AUTH_DOMAIN="tinyauth.example.com"
POCKET_ID_DOMAIN="pocket-id.example.com"
POCKET_ID_NAME="Pocket ID"
SECRET=some-random-32-chars-string
GENERIC_CLIENT_ID="your-pocket-id-client-id"
GENERIC_CLIENT_SECRET="your-pocket-id-client-secret"
# --- DO NOT EDIT BELOW THIS LINE ---
APP_URL="https://${TINY_AUTH_DOMAIN}"
GENERIC_AUTH_URL="https://${POCKET_ID_DOMAIN}/authorize"
GENERIC_TOKEN_URL="https://${POCKET_ID_DOMAIN}/api/oidc/token"
GENERIC_USER_URL="https://${POCKET_ID_DOMAIN}/api/oidc/userinfo"
GENERIC_SCOPES="openid email profile groups"
GENERIC_NAME="${POCKET_ID_NAME}"
注释已经写得很清楚了,这里需要修改的部分是:
TINY_AUTH_DOMAIN
: TinyAuth 的域名。POCKET_ID_DOMAIN
: Pocket ID 的域名。GENERIC_CLIENT_ID
: 在 Pocket ID 创建应用时获得的 Client ID。GENERIC_CLIENT_SECRET
: 在 Pocket ID 创建应用时获得的 Client Secret。POCKET_ID_NAME
: Pocket ID 的名称,可以随意设置,不会影响功能。SECRET
: 使用openssl rand -hex 16
生成一个随机字符串,用于加密和签名。
编辑好 docker.env
后,运行 docker compose up -d
即可启动。
为 echo 服务启用认证代理
接下来,我们需要为 echo
服务添加 Traefik 的 labels,以便使用 TinyAuth 进行认证。echo
服务的 Docker Compose 文件如下:
name: echo
services:
echo:
container_name: echo
image: luotianyi/echo:latest
restart: unless-stopped
networks:
- proxy
labels:
- "tinyauth.domain=echo.skyone.dev"
- "traefik.enable=true"
- "traefik.http.routers.echo.entrypoints=websecure"
- "traefik.http.routers.echo.rule=Host(`echo.skyone.dev`)"
- "traefik.http.routers.echo.service=echo"
- "traefik.http.services.echo.loadbalancer.server.port=5000"
- "traefik.http.routers.echo.middlewares=tinyauth"
networks:
proxy:
external: true
只需要注意两行:
tinyauth.domain=echo.skyone.host
: 这里的域名需要与 echo 服务的域名一致。traefik.http.routers.echo.middlewares=tinyauth
: 这行表示使用 TinyAuth 进行认证,这个中间件来自tinyauth
容器的 labels。
你可以将这两行添加到你的任意需要认证的服务中,不需要别的操作即可实现认证。
测试认证
现在,你可以访问 https://echo.skyone.dev
,会被重定向到 TinyAuth 的登录页面。登录后,你将被重定向回 echo
服务。
注意,这里 TinyAuth 生成的 Cookie 位于 .skyone.dev
域名下,这就是 TinyAuth 和 echo
服务需要在同一个域名下的原因。
TinyAuth 域名 | 服务域名 | 是否能共享 Cookie | 说明 |
---|---|---|---|
auth.skyone.dev | echo.skyone.dev | ✅ 可以 | 同属于 skyone.dev ,Cookie 有效 |
auth.skyone.dev | grafana.skyone.dev | ✅ 可以 | 也在 skyone.dev 下,Cookie 有效 |
auth.skyone.dev | echo.other.skyone.dev | ✅ 可以 | 虽然多一层子域,但仍在 skyone.dev 下,Cookie 有效 |
auth.skyone.dev | echo.other.dev | ❌ 不可以 | 根域名不同(skyone.dev ≠ other.dev ) |
auth1.skyone.dev | auth2.skyone.dev | ✅ 可以 | 都在 skyone.dev 下,Cookie 有效 |
auth.other.skyone.dev | echo.skyone.dev | ❌ 不可以 | .other.skyone.dev 不包括 echo.skyone.dev |
权限管理
TinyAuth + Pocket ID 的组合可以实现简单的权限管理。你可以在 Pocket ID 的管理面板中为不同的用户分配不同的权限。
例如,我希望 echo 服务只能被 admin
组的用户访问,可以在 Pocket ID 的管理面板中创建一个 admin
组,并将用户添加到该组中。然后在 echo 服务的 labels 中添加以下行:
- "tinyauth.oauth.groups=admin"
完成,当用户访问 echo
服务时,TinyAuth 会检查用户是否属于 admin
组,如果不属于,则会被拒绝访问。
同样的,也可以通过用户的邮箱来限制访问,例如:
- "tinyauth.oauth.whitelist=user1@example.com,/@regex\\.com$/,user2@example.com"
可以看到,支持正则表达式(注意转义),还是很不错的。
通过这种方式,TinyAuth 不仅能提供统一的登录入口,还能与 Pocket ID 的用户和组管理结合,实现精细化的访问控制。
【完】