openidc: OpenID Connect Relying Party 和 OAuth 2.0 资源服务器在 NGINX / nginx-module-lua 中的 Lua 实现
安装
如果您尚未设置 RPM 仓库订阅,请 注册。然后您可以继续以下步骤。
CentOS/RHEL 7 或 Amazon Linux 2
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-openidc
CentOS/RHEL 8+、Fedora Linux、Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-openidc
要在 NGINX 中使用此 Lua 库,请确保已安装 nginx-module-lua。
本文档描述了 lua-resty-openidc v1.8.0,于 2024 年 9 月 13 日发布。
lua-resty-openidc
lua-resty-openidc 是一个用于 NGINX 的库,实现了 OpenID Connect Relying Party (RP) 和/或 OAuth 2.0 Resource Server (RS) 功能。
作为 OpenID Connect Relying Party 使用时,它通过 OpenID Connect Discovery 和基本客户端配置(即授权码流程)对用户进行身份验证。作为 OAuth 2.0 资源服务器使用时,它可以针对授权服务器验证 OAuth 2.0 Bearer 访问令牌,或者在使用 JSON Web Token 作为访问令牌时,可以针对预配置的密钥/秘密进行验证。
它通过利用 lua-resty-session 维护经过身份验证的用户会话,从而提供在客户端浏览器 Cookie 中存储会话状态或使用服务器端存储机制 shared-memory|memcache|redis 的可配置选择。
它支持全服务器范围内缓存已解析的 Discovery 文档和验证的访问令牌。
它可以用作反向代理,在源服务器前终止 OAuth/OpenID Connect,从而保护源服务器/服务,遵循相关标准,而无需在服务器本身实现这些标准。
Google+ 登录的示例配置
用于对 Google+ 登录进行用户身份验证的示例 nginx.conf 配置,保护反向代理路径。
events {
worker_connections 128;
}
http {
resolver 8.8.8.8;
lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
lua_ssl_verify_depth 5;
# 用于发现元数据文档的缓存
lua_shared_dict discovery 1m;
# 用于 JWK 的缓存
lua_shared_dict jwks 1m;
# 注意:如果您有 "lua_code_cache off;",请使用:
# set $session_secret xxxxxxxxxxxxxxxxxxx;
# 参见:https://github.com/bungle/lua-resty-session#notes-about-turning-lua-code-cache-off
server {
listen 8080;
location / {
access_by_lua_block {
local opts = {
-- 完整的重定向 URI 必须由此脚本保护
-- 如果 URI 以 / 开头,完整的重定向 URI 变为
-- ngx.var.scheme.."://"..ngx.var.http_host..opts.redirect_uri
-- 除非使用 opts.redirect_uri_scheme 或传入请求中的 X-Forwarded-Proto 头覆盖了方案
redirect_uri = "https://MY_HOST_NAME/redirect_uri",
-- 在版本 1.6.1 之前,您会指定
-- redirect_uri_path = "/redirect_uri",
-- 并且无法设置主机名
-- OP 的发现端点。启用以获取所有端点的 URI(令牌、检查、注销...)
discovery = "https://accounts.google.com/.well-known/openid-configuration",
-- 访问 OP 令牌端点需要身份验证。支持多种身份验证模式:
--token_endpoint_auth_method = ["client_secret_basic"|"client_secret_post"|"private_key_jwt"|"client_secret_jwt"],
-- o 如果 token_endpoint_auth_method 设置为 "client_secret_basic"、"client_secret_post" 或 "client_secret_jwt",则对令牌端点的身份验证使用 client_id 和 client_secret
-- 对于不符合 OAuth 2.0 RFC 6749 的 OP(参见 https://tools.ietf.org/html/rfc6749#section-2.3.1)
-- client_id 和 client_secret 在 URL 编码时必须保持不变
client_id = "<client_id>",
client_secret = "<client_secret>",
-- o 如果 token_endpoint_auth_method 设置为 "private_key_jwt",则对令牌端点的身份验证使用 client_id、client_rsa_private_key 和 client_rsa_private_key_id 来计算签名的 JWT
-- client_rsa_private_key 是用于签署 lua-resty-openidc 生成的 JWT 的 RSA 私钥,用于对 OP 进行身份验证
-- client_rsa_private_key_id(可选)是要在 JWT 头中设置的密钥 ID,以标识 OP 应使用哪个公钥来验证 JWT 签名
--client_id = "<client_id>",
--client_rsa_private_key=[[-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAiThmpvXBYdur716D2q7fYKirKxzZIU5QrkBGDvUOwg5izcTv
[...]
h2JHukolz9xf6qN61QMLSd83+kwoBr2drp6xg3eGDLIkQCQLrkY=
-----END RSA PRIVATE KEY-----]],
--client_rsa_private_key_id="key id#1",
-- 由 lua-resty-openidc 生成的用于对 OP 进行身份验证的签名 JWT 的有效期(以秒为单位)。
-- (在 token_endpoint_auth_method 设置为 "private_key_jwt" 或 "client_secret_jwt" 身份验证时使用)。默认是 60 秒。
--client_jwt_assertion_expires_in = 60,
-- 使用 https 访问任何 OP 端点时,可以强制 SSL 证书检查("yes")或不强制("no")。
--ssl_verify = "no",
-- 与 OP 的连接保持活动可以启用("yes")或禁用("no")。
--keepalive = "no",
--response_mode=form_post 可用于使 lua-resty-openidc 使用 [OAuth 2.0 表单提交响应模式](https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html)。*注意* 对于现代浏览器,您需要将 [`$session_cookie_samesite`](https://github.com/bungle/lua-resty-session#string-sessioncookiesamesite) 设置为 `None`,除非您的 OpenID Connect 提供者和 Relying Party 共享相同的域。
--authorization_params = { hd="zmartzone.eu" },
--scope = "openid email profile",
-- 在不需要重新身份验证的情况下,每 900 秒刷新用户的 id_token
--refresh_session_interval = 900,
--iat_slack = 600,
--redirect_uri_scheme = "https",
--logout_path = "/logout",
--redirect_after_logout_uri = "/",
-- 用户从 RP 注销后应重定向到哪里。此选项覆盖 OP 在发现响应中可能提供的任何 end_session_endpoint。
--redirect_after_logout_with_id_token_hint = true,
-- 注销后重定向是否应包含 id token 作为提示(如果可用)。此选项仅在设置了 redirect_after_logout_uri 时使用。
--post_logout_redirect_uri = "https://www.zmartzone.eu/logoutSuccessful",
-- RP 请求 OP 在注销后重定向用户到哪里。如果此选项设置为相对 URI,则相对于 OP 的注销端点,而不是 RP 的。
--accept_none_alg = false
-- 如果您的 OpenID Connect 提供者不签署其 id tokens
-- (使用 "none" 签名算法),则将其设置为 true。
--accept_unsupported_alg = true
-- 如果您想拒绝使用 lua-resty-jwt 不支持的算法签名的令牌,则将其设置为 false。如果
-- 您不设置或将其设置为 true,则在使用不支持的算法时不会验证令牌签名。
--renew_access_token_on_expiry = true
-- 此插件是否应尝试在访问令牌过期后静默续订访问令牌,如果有可用的刷新令牌。
-- 如果续订令牌失败,用户将被重定向到授权端点。
--access_token_expires_in = 3600
-- 如果令牌端点响应中没有 expires_in 属性,则 access_token 的默认生命周期(以秒为单位)。
--access_token_expires_leeway = 0
-- 访问令牌续订的过期宽限。如果设置,则续订将在访问令牌过期前 access_token_expires_leeway 秒进行。这避免了在访问令牌刚好在到达 OAuth 资源服务器时过期的错误。
--force_reauthorize = false
-- 当 force_reauthorize 设置为 true 时,即使已经缓存了令牌,也将执行授权流程
--session_contents = {id_token=true}
-- 要启用的会话内容白名单。这可以用来减少会话大小。
-- 未设置时,所有内容都将包含在会话中。
-- 可用的有:
-- id_token, enc_id_token, user, access_token(包括刷新令牌)
-- 您可以为连接/发送/读取指定超时,作为单个数字(设置所有超时)或作为表。值以毫秒为单位
-- timeout = 1000
-- timeout = { connect = 500, send = 1000, read = 1000 }
--use_nonce = false
-- 默认情况下,授权请求包括 nonce 参数。您可以使用此选项禁用它
-- 这在与忽略参数的损坏 OpenID 连接提供者交互时可能是必要的,因为
-- 否则 id_token 将被拒绝。
--revoke_tokens_on_logout = false
-- 当 revoke_tokens_on_logout 设置为 true 时,注销会通知授权服务器,之前获得的刷新和访问令牌不再需要。这要求撤销端点是可发现的。
-- 如果未提供撤销端点或撤销时出现错误,用户将不会被通知,注销过程将正常继续。
-- 可选:使用代理选项表为 OpenID Connect 提供者端点添加出站代理:
-- 这需要 lua-resty-http >= 0.12
-- proxy_opts = {
-- http_proxy = "http://<proxy_host>:<proxy_port>/",
-- https_proxy = "http://<proxy_host>:<proxy_port>/"
-- }
-- 生命周期钩子
--
-- lifecycle = {
-- on_created = handle_created,
-- on_authenticated = handle_authenticated,
-- on_regenerated = handle_regenerated
-- on_logout = handle_logout
-- }
--
-- 其中 `handle_created`、`handle_authenticated`、`handle_regenerated` 和 `handle_logout` 是可调用的
-- 接受参数 `session`。`handle_created` 还接受第二个参数 `params`,这是一个表
-- 包含用于将用户重定向到 OpenID 连接提供者端点的授权请求的查询参数。
--
-- -- `on_created` 钩子在
-- `openidc_authorize` 中创建会话后立即调用,在保存会话之前
-- -- `on_authenticated` 钩子在
-- `openidc_authorization_response` 中接收到授权响应后立即调用,在保存会话之前
-- 从 lua-resty-openidc 1.7.5 开始,这将接收解码的 id_token 作为第二个参数,令牌端点的响应作为第三个参数
-- -- `on_regenerated` 在
-- 通过令牌刷新获得新访问令牌后立即调用,并使用重新生成的会话表调用
-- -- `on_logout` 钩子在
-- `openidc_logout` 中销毁会话之前调用
--
-- 可以使用任何、所有或没有钩子。空的 `lifecycle` 不执行任何操作。
-- 返回真值的钩子会导致它们参与的生命周期操作失败。
-- 可选:为 HTTP 请求添加装饰器
-- 在 lua-resty-openidc 直接与 OpenID Connect
-- 提供者通信时应用。可用于提供额外的 HTTP 头
-- 或添加其他类似行为。
-- http_request_decorator = function(req)
-- local h = req.headers or {}
-- h[EXTRA_HEADER] = 'my extra header'
-- req.headers = h
-- return req
-- end,
-- use_pkce = false,
-- 设置为 true 时,将使用 RFC 7636 中定义的 "Proof Key for Code Exchange"。代码挑战方法将始终为 S256
}
-- 调用 authenticate 进行 OpenID Connect 用户身份验证
local res, err = require("resty.openidc").authenticate(opts)
if err then
ngx.status = 500
ngx.say(err)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
-- 此时 res 是一个包含 3 个键的 Lua 表:
-- id_token : 包含 id_token 中声明的 Lua 表(必需)
-- access_token: 访问令牌(可选)
-- user : 从用户信息端点返回的声明的 Lua 表(可选)
--if res.id_token.hd ~= "zmartzone.eu" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
--if res.user.email ~= "[email protected]" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
-- 设置带有用户信息的头:这将覆盖任何现有的头
-- 但在令牌中未提供值时也会清除它们(!)
ngx.req.set_header("X-USER", res.id_token.sub)
}
proxy_pass http://localhost:80;
}
}
}
关于 redirect_uri
所谓的 redirect_uri 是 OpenID Connect 协议的一部分。重定向 URI 在您的 OpenID Connect 提供者处注册,是您的提供者在成功登录后将用户重定向到的 URI。此 URI 然后由 lua-resty-openidc 处理,在此获取令牌并执行一些检查,只有在此之后,浏览器才会重定向到用户最初想要去的地方。
redirect_uri 不应由您的应用程序代码处理。它必须是 lua-resty-openidc 负责的 URI,因此必须在 lua-resty-openidc 保护的 location 中。
您通过 opts.redirect_uri 参数在 lua-resty-openidc 端配置 redirect_uri(默认为 /redirect_uri)。如果它以 / 开头,则 lua-resty-openidc 在将 URI 发送到 OpenID Connect 提供者时会在前面添加协议和当前主机名(考虑 Forwarded 和 X-Forwarded-* HTTP 头)。但您也可以自己指定包含主机和协议的绝对 URI。
在版本 1.6.1 之前,opts.redirect_uri_path 是配置 redirect_uri 的方式,而没有任何选项来控制协议和主机部分。
每当 lua-resty-openidc "看到" 导航到与 opts.redirect_uri(或 opts.redirect_uri_path)匹配的本地路径时,它将拦截请求并自行处理。
这在大多数情况下有效,但有时外部可见的 redirect_uri 与服务器本地可见的路径不同。如果在您的服务器前有一个反向代理在转发请求之前重写 URI,则可能会发生这种情况。因此,版本 1.7.6 引入了一个新选项 opts.local_redirect_uri_path。如果设置了此选项,lua-resty-openidc 将拦截对该路径的请求,而不是 opts.redirect_uri 的路径。
仅检查身份验证
-- 检查会话,但如果尚未登录,则不重定向到身份验证
local res, err = require("resty.openidc").authenticate(opts, nil, "pass")
仅检查身份验证并拒绝未认证访问
-- 检查会话,如果尚未登录则不重定向到身份验证,而是返回错误
local res, err = require("resty.openidc").authenticate(opts, nil, "deny")
会话和锁定
authenticate 函数将当前会话对象作为其第四个返回参数返回。如果您已配置 lua-resty-session 使用具有锁定的服务器端存储后端,则返回时会话可能仍处于锁定状态。在这种情况下,您可能希望显式关闭它。
local res, err, target, session = require("resty.openidc").authenticate(opts)
session:close()
缓存
lua-resty-openidc 可以使用 共享内存缓存 来处理多项内容。如果您希望它使用缓存,必须在 nginx.conf 文件中使用 lua_shared_dict。
当前使用最多四个缓存:
- 名为
discovery的缓存存储您的 OpenID Connect 提供者的 OpenID Connect Discovery 元数据。缓存项在 24 小时后过期,除非被opts.discovery_expires_in(以秒为单位的值)覆盖。此缓存将为每个发行者 URI 存储一个项目,您可以自行查找发现文档以获取所需大小的估算 - 通常每个 OpenID Connect 提供者几 KB。 - 名为
jwks的缓存存储您的 OpenID Connect 提供者的密钥材料(如果通过 JWKS 端点提供)。缓存项在 24 小时后过期,除非被opts.jwks_expires_in覆盖。此缓存将为每个 JWKS URI 存储一个项目,您可以自行查找 jwks 以获取所需大小的估算 - 通常每个 OpenID Connect 提供者几 KB。 - 名为
introspection的缓存存储 OAuth2 令牌检查的结果。缓存项在相应的令牌过期时过期。未知过期的令牌根本不缓存。此缓存将包含每个被检查的访问令牌的一个条目 - 通常每个令牌几 KB。 - 名为
jwt_verification的缓存存储 JWT 验证的结果。缓存项在相应的令牌过期时过期。未知过期的令牌在两分钟内不缓存。此缓存将包含每个经过验证的 JWT 的一个条目 - 通常每个令牌几 KB。
检查和 JWT 验证结果的缓存
请注意,jwt_verification 和 introspection 缓存在所有配置的位置之间共享。如果您使用具有不同 opts 配置的位置,则共享缓存可能允许仅对一个位置有效的令牌被另一个位置接受(如果它是从缓存中读取的)。为了避免缓存混淆,建议为每组相关位置将 opts.cache_segment 设置为唯一字符串。
撤销令牌
revoke_tokens(opts, session) 函数撤销当前的刷新和访问令牌。与完全注销相比,会话 Cookie 不会被销毁,结束会话端点也不会被调用。该函数在两个令牌成功撤销时返回 true。在您希望从服务器端销毁/删除会话的场景中,此函数可能会很有帮助。
使用 revoke_token(opts, token_type_hint, token) 也可以撤销特定的令牌。token_type_hint 通常可以是 refresh_token 或 access_token。
OAuth 2.0 JWT 令牌验证的示例配置
用于验证 Bearer JWT 访问令牌与预配置的密钥/秘密的示例 nginx.conf 配置。
一旦成功验证,NGINX 服务器可以作为内部源服务器的反向代理。
events {
worker_connections 128;
}
http {
resolver 8.8.8.8;
# 用于 JWT 验证结果的缓存
lua_shared_dict jwt_verification 10m;
server {
listen 8080;
location /api {
access_by_lua '
local opts = {
-- 1. HS??? 签名验证的共享密钥示例
--symmetric_key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-- 在版本 1.6.1 之前,此选项的密钥将是 secret
-- 而不是 symmetric_key
-- 2. RS??? 签名验证的公钥示例
public_key = [[-----BEGIN CERTIFICATE-----
MIIC0DCCAbigAwIBAgIGAVSbMZs1MA0GCSqGSIb3DQEBCwUAMCkxCzAJBgNVBAYTAlVTMQwwCgYD
VQQKEwNibGExDDAKBgNVBAMTA2JsYTAeFw0xNjA1MTAxNTAzMjBaFw0yNjA1MDgxNTAzMjBaMCkx
CzAJBgNVBAYTAlVTMQwwCgYDVQQKEwNibGExDDAKBgNVBAMTA2JsYTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAIcLtHjX2GFxYv1033dvfohyCU6nsuR1qoDXfHTG3Mf/Yj4BfLHtMjJr
nR3sgHItH3B6qZPnfErfsN0LP4uZ10/74CrWVqT5dy6ecXMqYtz/KNJ8rG0vY8vltc417AU4fie8
gyeWv/Z6wHWUCf3NHRV8GfFgfuvywgUpHo8ujpUPFr+zrPr8butrzJPq1h3+r0f5P45tfWOdpjCT
gsTzK6urUG0k3WkwdDYapL3wRCAw597nYfgKzzXuh9N0ZL3Uj+eJ6BgCzUZDLXABpMBZfk6hmmzp
cAFV4nTf1AaAs/EOwVE0YgZBJiBrueMcteAIxKrKjEHgThU2Zs9gN9cSFicCAwEAATANBgkqhkiG
9w0BAQsFAAOCAQEAQLU1A58TrSwrEccCIy0wxiGdCwQbaNMohzirc41zRMCXleJXbtsn1vv85J6A
RmejeH5f/JbDqRRRArGMdLooGbqjWG/lwZT456Q6DXqF2plkBvh37kp/GjthGyR8ODJn5ekZwxuB
OcTuruRhqYOIJjiYZSgK/P0zUw1cjLwUJ9ig/O6ozYmof83974fygA/wK3SgFNEoFlTkTpOvZhVW
9kLfCVA/CRBfJNKnz5PWBBxd/3XSEuP/fcWqKGTy7zZso4MTB0NKgWO4duGTgMyZbM4onJPyA0CY
lAc5Csj0o5Q+oEhPUAVBIF07m4rd0OvAVPOCQ2NJhQSL1oWASbf+fg==
-----END CERTIFICATE-----]],
-- 在版本 1.6.1 之前,此选项的密钥将是 secret
-- 而不是 public_key
-- 3. 或者可以指向所谓的 Discovery 文档,该文档
-- 包含 "jwks_uri" 条目;jwks 端点必须提供 "x5c" 条目
-- 或 RSA 签名验证的 "n" 模数和 "e" 指数条目
-- discovery = "https://accounts.google.com/.well-known/openid-configuration",
-- 您期望使用的签名算法;
-- 可以是单个字符串或表。
-- 出于安全原因,您应该为此设置
-- 以避免接受声称由 HMAC 签名的令牌
-- 使用公钥 RSA。
--token_signing_alg_values_expected = { "RS256" }
-- 如果您想接受未签名的令牌(使用
-- "none" 签名算法),则将其设置为 true。
--accept_none_alg = false
-- 如果您想拒绝使用 lua-resty-jwt 不支持的算法签名的令牌,则将其设置为 false。如果
-- 您不设置,则不会验证令牌签名。
--accept_unsupported_alg = true
-- jwk 缓存的过期时间(以秒为单位),默认是 1 天。
--jwk_expires_in = 24 * 60 * 60
-- 可能需要强制验证 Bearer 令牌并忽略现有的缓存
-- 验证结果。如果是这样,您需要将 jwt_verification_cache_ignore 选项设置为 true。
-- jwt_verification_cache_ignore = true
-- 如果您需要为不同配置的位置设置单独的缓存,则可选缓存段名称
-- cache_segment = 'api'
}
-- 调用 bearer_jwt_verify 进行 OAuth 2.0 JWT 验证
local res, err = require("resty.openidc").bearer_jwt_verify(opts)
if err or not res then
ngx.status = 403
ngx.say(err and err or "未提供 access_token")
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- 此时 res 是一个表示(验证过的)JSON 的 Lua 表
-- 负载在 JWT 令牌中;现在我们通常不想允许任何
-- 由授权服务器签发的令牌,而是希望通过客户端 ID 或作用域应用
-- 一些访问限制
--if res.scope ~= "edit" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
--if res.client_id ~= "ro_client" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
';
proxy_pass http://localhost:80;
}
}
}
PingFederate OAuth 2.0 的示例配置
用于验证 Bearer 访问令牌与 PingFederate OAuth 2.0 授权服务器的示例 nginx.conf 配置。
events {
worker_connections 128;
}
http {
resolver 8.8.8.8;
lua_ssl_trusted_certificate /opt/local/etc/openssl/cert.pem;
lua_ssl_verify_depth 5;
# 用于验证结果的缓存
lua_shared_dict introspection 10m;
server {
listen 8080;
location /api {
access_by_lua '
local opts = {
introspection_endpoint="https://localhost:9031/as/introspect.oauth2",
client_id="rs_client",
client_secret="2Federate",
ssl_verify = "no",
-- 默认为 "exp" - 控制 introspection 缓存的 TTL
-- https://tools.ietf.org/html/rfc7662#section-2.2
-- introspection_expiry_claim = "exp"
-- 如果您需要为不同配置的位置设置单独的缓存,则可选缓存段名称
-- cache_segment = 'api'
}
-- 调用 introspect 进行 OAuth 2.0 Bearer 访问令牌验证
local res, err = require("resty.openidc").introspect(opts)
if err then
ngx.status = 403
ngx.say(err)
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- 此时 res 是一个表示 JSON 的 Lua 表
-- 从检查/验证端点返回的对象
--if res.scope ~= "edit" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
--if res.client_id ~= "ro_client" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
';
}
}
}
作为 Cookie 传递 Bearer OAuth 2.0 访问令牌的示例配置
用于验证作为 Cookie 传递的 Bearer 访问令牌与 ORY/Hydra 授权服务器的示例 nginx.conf 配置。
events {
worker_connections 128;
}
http {
resolver 8.8.8.8;
lua_ssl_trusted_certificate /opt/local/etc/openssl/cert.pem;
lua_ssl_verify_depth 5;
# 用于验证结果的缓存
lua_shared_dict introspection 10m;
server {
listen 8080;
location /api {
access_by_lua '
local opts = {
-- 设置检查端点的 URI
introspection_endpoint="https://localhost:9031/oauth2/introspect",
-- 或者,如果您的 OAuth2 提供者提供包含
-- introspection_endpoint 声明的发现文档,您可以将 introspection_endpoint 选项
-- 保持未设置,而是使用
-- discovery = "https://my-oauth2-provider/.well-known/oauth-authorization-server",
client_id="admin",
client_secret="demo-password",
ssl_verify = "no",
-- 定义在缓存的访问令牌需要
-- 通过再次检查(和验证)它来刷新之前的时间间隔(以秒为单位)。
-- 未定义时,值为 0,这意味着它仅在授权服务器返回的 `exp`(或替代值,
-- 参见 introspection_expiry_claim)后过期
-- introspection_interval = 60,
-- 定义 Bearer OAuth 2.0 访问令牌可以传递给此资源服务器的方式。
-- "cookie" 作为名为 "PA.global" 的 Cookie 头,或使用在 ":" 后指定的名称
-- "header" "Authorization: bearer" 头
-- 未定义时,使用默认的 "Authorization: bearer" 头
-- auth_accept_token_as = "cookie:PA",
-- 如果使用头,则头字段为 Authorization
-- auth_accept_token_as_header_name = "cf-Access-Jwt-Assertion"
-- OAuth 2.0 授权服务器检查端点的身份验证方法,
-- 用于使用 client_id/client_secret 对客户端进行身份验证
-- 默认为 "client_secret_post"
-- introspection_endpoint_auth_method = "client_secret_basic",
-- 指定要从浏览器中提取并在与 OP 和 AS 端点的后端通话中发送的 Cookie 名称,以空格分隔。
-- 未定义时,不发送此类 Cookie。
-- pass_cookies = "JSESSION"
-- 默认为 "exp" - 控制 introspection 缓存的 TTL
-- https://tools.ietf.org/html/rfc7662#section-2.2
-- introspection_expiry_claim = "exp"
-- 可能需要强制对 access_token 进行检查并忽略现有的缓存
-- 检查结果。如果是这样,您需要将 introspection_cache_ignore 选项设置为 true。
-- introspection_cache_ignore = true
-- 如果您需要为不同配置的位置设置单独的缓存,则可选缓存段名称
-- cache_segment = 'api'
}
-- 调用 introspect 进行 OAuth 2.0 Bearer 访问令牌验证
local res, err = require("resty.openidc").introspect(opts)
if err then
ngx.status = 403
ngx.say(err)
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- 此时 res 是一个表示 JSON 的 Lua 表
-- 从检查/验证端点返回的对象
--if res.scope ~= "edit" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
--if res.client_id ~= "ro_client" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
';
}
}
}
日志记录
日志记录可以自定义,包括使用自定义记录器和重新映射 OpenIDC 的默认日志级别,例如:
local openidc = require("resty.openidc")
openidc.set_logging(nil, { DEBUG = ngx.INFO })
运行测试
我们创建了一个 Docker 化的测试环境,以简化依赖项的安装。
要运行测试,请执行
$ docker build -f tests/Dockerfile . -t lua-resty-openidc/test
$ docker run -it --rm lua-resty-openidc/test:latest
如果您希望在测试时创建 luacov 覆盖,请使用
$ docker run -it --rm -e coverage=t lua-resty-openidc/test:latest
作为第二个命令
支持
有关常见问题的通用问题,请参阅维基页面中的常见问题解答: https://github.com/zmartzone/lua-resty-openidc/wiki 任何问题/问题应提交至 GitHub 讨论或问题跟踪器。
免责声明
此软件由 ZmartZone IAM 开源,但不提供商业支持。 任何问题/问题应提交至 GitHub 讨论或问题跟踪器。 另请参阅此目录中的免责声明文件。
GitHub
您可以在 nginx-module-openidc 的 GitHub 仓库 中找到有关此模块的其他配置提示和文档。
