OIDC 身份验证设置#

本指南说明如何使用 Google 作为身份提供商 和 Angie Web 服务器通过 Lua 脚本设置 OpenID Connect (OIDC) 身份验证。

该实现使用 OAuth2/OIDC 身份验证保护内部端点, 并演示了一种基于电子邮件域限制访问的方法。 这只是一种示例方法;您可以按照自己喜欢的方式实现访问控制, 例如维护特定用户的允许列表、检查提供商响应中的域成员资格 或组属性,或使用来自您私有 IAM 系统的自定义声明。

小技巧

此 OIDC 实现为身份验证提供了基础,但应根据生产环境进行调整, 采用适当的安全措施、监控以及符合您组织的安全策略。

架构#

此处建议的 OIDC 设置包括:

  • Angie - 支持 Lua 模块以进行 OIDC 处理

  • lua-resty-openidc - 用于 OIDC 身份验证的 OpenResty Lua 库

  • Google OAuth2 - 用于用户身份验证的身份提供商

  • Docker Compose - 在本示例中仅用于快速启动; 在生产环境中使用您喜欢的任何部署方法

前提条件#

在配置 OIDC 身份验证之前,请确保您具备:

  1. 支持 Lua 模块 的 Angie Web 服务器

  2. Docker 和 Docker Compose(用于部署)

  3. Google Cloud Console 项目

  4. 来自 Google 的 OAuth2 凭据

Google OAuth2 设置#

要将 Google 配置为您的 OIDC 提供商:

  1. 导航到 Google Cloud Console

  2. 创建新项目或选择现有项目

  3. 为您的项目配置 OAuth 同意屏幕(外部或内部)并发布它,以便用户可以进行身份验证

  4. 创建 OAuth2 凭据:

    • 应用类型: Web 应用程序

    • 已授权的重定向 URI: http://localhost/auth/callback

  5. 保存您的 client_idclient_secret 以供配置使用

备注

标准 Google Identity Services 已经支持 OIDC;不需要旧版 Google+ API。 仅当您的应用程序需要其数据时才启用其他 Google API。

配置设置#

让我们从 OIDC 设置所需的配置文件开始。

Docker Compose 配置#

Docker 部署使用以下配置文件:

docker-compose.yml#
services:
  angie:
    image: docker.angie.software/angie:templated
    environment:
      ANGIE_LOAD_MODULES: "lua"
    ports:
      - 80:80
    volumes:
      - ./files/etc/angie/http.d:/etc/angie/http.d

此配置执行以下操作:

对于即插即用的演示, 下载 OIDC 快速启动包, 在 files/etc/angie/http.d/oidc.lua 中设置您的 client_idclient_secret, 一切都将开箱即用。

OIDC 身份验证脚本#

创建一个 OIDC 身份验证脚本, 使用 lua-resty-openidc 库处理身份验证逻辑:

/etc/angie/http.d/oidc.lua#
access_by_lua_block {
    local res, err = require("resty.openidc").authenticate({
        redirect_uri = "http://localhost/auth/callback",
        discovery = "https://accounts.google.com/.well-known/openid-configuration",
        logout_path = "/auth/logout",
        redirect_after_logout_uri = "/auth/logged-out",
        revoke_tokens_on_logout = true,
        client_id = "YOUR_CLIENT_ID",
        client_secret = "YOUR_CLIENT_SECRET"
    })
}

配置参数:

  • redirect_uri: 成功身份验证后的回调 URL

  • discovery: Google 的 OIDC 发现端点

  • logout_path: 用户注销路径

  • redirect_after_logout_uri: 注销后的重定向目标

  • revoke_tokens_on_logout: 注销时撤销令牌以确保安全

  • client_idclient_secret: 您的 Google OAuth2 凭据

Angie 配置#

使用必要的 location 块配置 Angie 以进行 OIDC 身份验证。

受保护的资源#

要使用 OIDC 身份验证保护资源:

location /internal/ {
    include /etc/angie/http.d/oidc.lua;
    proxy_pass http://127.0.0.1/status/;
}

此配置执行以下操作:

  • 使用 OIDC 身份验证保护 /internal/ 路径

  • 将经过身份验证的请求代理到 /status/内部 API

身份验证端点#

配置 OAuth2 流程端点:

location /auth/callback {
    include /etc/angie/http.d/oidc.lua;
}

location /auth/logout {
    include /etc/angie/http.d/oidc.lua;
}

location /auth/logged-out {
    default_type text/plain;
    return 200 "You have been logged out. Bye!";
}

端点功能:

  • /auth/callback: 处理来自 Google 的 OAuth2 回调

  • /auth/logout: 启动用户注销

  • /auth/logged-out: 成功注销后的着陆页

内部 API 访问#

配置对内部 API 的受限访问:

location /status/ {
    api     /status/;
    allow   127.0.0.1;
    deny    all;
}

这提供了:

  • 访问 Angie 的 状态 API

  • 仅限本地主机访问 (127.0.0.1)

  • 通过 /internal/ 访问时的 OIDC 保护

部署步骤#

按照以下步骤部署 OIDC 身份验证:

配置更新#

  1. 在您的 OIDC Lua 脚本中更新 OAuth2 凭据:

    替换 oidc.lua 中的占位符值:

    • client_id 替换为您的 Google OAuth2 客户端 ID

    • client_secret 替换为您的 Google OAuth2 客户端密钥

服务启动#

  1. 启动 Docker 服务:

    $ docker-compose up -d
    
  2. 验证部署:

    • 导航到 http://localhost/internal/

    • 您应该被重定向到 Google 进行身份验证

    • 成功登录后,您将访问受保护的内容

安全配置#

电子邮件域限制#

实现域验证以按电子邮件域限制访问:

if not string.match(res.user.email, "gmail.com$") then
    ngx.exit(ngx.HTTP_FORBIDDEN)
end

对于生产环境,请考虑以下事项:

  • gmail.com 替换为您组织的域

  • 实现允许的电子邮件地址白名单

  • 添加基于角色的访问控制

令牌管理#

OIDC 实现包括安全功能:

  • 注销时自动撤销令牌 (revoke_tokens_on_logout = true)

  • lua-resty-openidc 库安全地管理会话

  • 所有身份验证流程都遵循 OAuth2/OIDC 安全最佳实践

警告

对于生产部署:

  • 始终对 OAuth2 回调使用 HTTPS

  • 安全地存储客户端密钥,切勿存储在版本控制中

  • 实施适当的会话超时和续订策略

  • 监控身份验证日志以发现安全事件

身份验证流程#

OIDC 身份验证流程遵循标准 OAuth2/OIDC 程序:

  1. 用户访问受保护的 URL(例如 http://localhost/internal/)

  2. 如果未经身份验证,用户将被重定向到 Google OAuth2

  3. 用户使用 Google 凭据进行身份验证

  4. Google 使用授权码重定向回 /auth/callback

  5. 服务器将代码交换为访问令牌和 ID 令牌

  6. 验证用户信息(包括电子邮件域检查)

  7. 授予用户访问受保护资源的权限

注销过程确保安全的会话终止:

  1. 用户导航到 http://localhost/auth/logout

  2. 在 Google 的 OAuth2 端点撤销令牌

  3. 清除本地会话数据

  4. 用户被重定向到 /auth/logged-out

高级配置#

要限制对特定组织域的访问:

if not string.match(res.user.email, "yourcompany.com$") then
    ngx.exit(ngx.HTTP_FORBIDDEN)
end

对于具有多个允许域的组织:

local allowed_domains = {"company1.com", "company2.com", "gmail.com"}
local email_valid = false

for _, domain in ipairs(allowed_domains) do
    if string.match(res.user.email, domain .. "$") then
        email_valid = true
        break
    end
end

if not email_valid then
    ngx.exit(ngx.HTTP_FORBIDDEN)
end

用户信息访问#

从 OIDC 提供商访问其他用户声明:

-- 从 ID 令牌访问用户信息
local user_name = res.user.name
local user_picture = res.user.picture
local user_locale = res.user.locale
local user_email = res.user.email

这些值可用于日志记录、个性化或其他访问控制决策。