OAuth 2.0 / OIDC

PicFast 支持通过 OAuth 2.0 和 OpenID Connect (OIDC) 进行第三方登录。 配置完成后,登录页会出现"使用 ... 登录"按钮,用户还可以在设置中关联或解绑第三方账号。

已支持的提供商

提供商类型说明
GitHub github 纯 OAuth 2.0。通过 /user/user/emails API 获取用户信息。
Keycloak oidc 完整 OIDC 支持,通过 .well-known/openid-configuration 自动发现端点,强制 PKCE。
任意 OIDC 提供商 oidc 使用 type: oidc 即可接入符合 OIDC 规范的提供商(Google、Microsoft、Authelia 等)。

配置方式

OAuth 提供商在 config.yamloauth.providers 下配置。 推荐通过 Docker Compose 挂载配置文件。

Docker Compose 挂载

docker-compose.yml 中添加 volume 挂载:

services:
  app:
    volumes:
      - ./config.yaml:/etc/picfast/config.yaml:ro
文件权限注意。 容器以 10001:10001 用户运行。 请确保 config.yaml 对该用户可读: chown 10001:10001 config.yaml && chmod 0644 config.yaml

GitHub

  1. GitHub 设置 → Developer settings → OAuth Apps 创建应用。
  2. Authorization callback URL 填写 https://你的域名/api/v1/auth/oauth/github/callback
  3. 复制 Client ID,生成 Client Secret
oauth:
  providers:
    - id: github
      display_name: GitHub
      type: github
      client_id: "Iv1.xxxxxxxxxxxx"
      client_secret: "ghs_xxxxxxxxxxxxxxxxxxxx"
      enabled: true

app:
  web_base_url: "https://picfast.example.com"

Keycloak(或其他 OIDC 提供商)

  1. 在 Keycloak Realm 中创建客户端:
    • Client type: OpenID Connect
    • Access type: confidential
    • Valid redirect URIs: https://你的域名/api/v1/auth/oauth/keycloak/callback
  2. 从 Credentials 标签页复制 Client IDClient Secret
oauth:
  providers:
    - id: keycloak
      display_name: "Keycloak SSO"
      type: oidc
      client_id: "picfast"
      client_secret: "你的 Keycloak Secret"
      issuer: "https://auth.example.com/realms/myrealm"
      enabled: true
      scopes:
        - openid
        - profile
        - email

app:
  web_base_url: "https://picfast.example.com"

其他 OIDC 提供商(不支持自动发现)

如果 OIDC 提供商不支持 Discovery(.well-known/openid-configuration),请保留 issuer(ID token 的 iss 校验依赖此项),并额外配置 auth_urltoken_urljwks_urluserinfo_url 可选。

oauth:
  providers:
    - id: custom-oidc
      display_name: "自定义 OIDC"
      type: oidc
      client_id: "your-client-id"
      client_secret: "your-secret"
      issuer: "https://idp.example.com"
      auth_url: "https://idp.example.com/authorize"
      token_url: "https://idp.example.com/token"
      userinfo_url: "https://idp.example.com/userinfo"
      jwks_url: "https://idp.example.com/certs"
      enabled: true

多提供商同时启用

oauth:
  providers:
    - id: keycloak
      display_name: "Keycloak SSO"
      type: oidc
      client_id: "picfast"
      client_secret: "..."
      issuer: "https://auth.example.com/realms/myrealm"
      enabled: true
    - id: github
      display_name: GitHub
      type: github
      client_id: "Iv1.xxx"
      client_secret: "ghs_xxx"
      enabled: true

必填配置项

配置项说明
app.web_base_url 启用 OAuth 时必填。 用户登录后跳转的前端地址,应填写用户实际访问的域名。
server.base_url 启用 OAuth 时必填。 用于构造 OAuth 回调 URL 的后端地址。
server.trusted_proxies 反向代理的 IP 地址列表(CIDR 格式)。使用 nginx/traefik 时需配置,否则 cookie 和客户端 IP 无法正常工作。

使用体验

  • 登录页: 提供商按钮显示在邮箱登录表单下方,带分隔线。
  • 账号关联: 已登录用户可在设置页关联或解绑第三方账号。
  • 自动绑定: 当 IdP 验证过的邮箱与已有账号匹配时,首次登录自动关联。
  • 防锁死: 如果没有设置密码,不允许解绑最后一个登录方式。

安全说明

  • OIDC 提供商强制 PKCE(S256 code challenge)。
  • State cookie 使用从 JWT secret 派生的 HMAC 签名防 CSRF。
  • 受信代理 是正确处理 X-Forwarded-Proto 和 X-Forwarded-For 的前提。
  • 自动绑定 仅在 IdP 声明 email_verified: true 时触发。