使用 auth_request 模块的 Nginx SSO 解决方案。 Vouch Proxy 可以同时保护您的所有网站。
Vouch Proxy 支持许多 OAuth 和 OIDC 登录提供程序,并且可以强制执行身份验证...
谷歌
GitHub
GitHub 企业版
独立认证
奥克塔
松弛
ADFS
Azure AD
阿里巴巴/阿里云iDaas
AWS认知
抽搐
不和谐
安全认证
吉泰亚
钥匙斗篷
PHP 的 OAuth2 服务器库
家庭助理
开放斯塔克斯
奥里九头蛇
下一云
大多数其他 OpenID Connect (OIDC) 提供商
当您使用首选 IdP 或库部署 Vouch Proxy 时,请告知我们,以便我们更新列表。
如果 Vouch 与 Nginx 反向代理在同一主机上运行,则从/validate
端点到 Nginx 的响应时间应小于 1ms 。
凭证代理的作用是什么...
安装与配置
验证代理“在路径中”
附加 Nginx 配置
通过环境变量进行配置
提示、技巧和高级配置
范围和权利要求
从 Docker 运行
Kubernetes Nginx 入口
从源代码编译并运行二进制文件
/login 和 /logout 端点重定向
故障排除、支持和功能请求(在 GitHub 提交问题之前请阅读本文)
我遇到无限重定向循环,该循环将我返回到我的 IdP (Google/Okta/GitHub/...)
好的,我查看了问题并尝试了一些配置,但仍然无法正常工作
为 Vouch Proxy 做出贡献
使用 OpenResty 进行高级授权
使用 Google Oauth 的登录和身份验证流程
凭证代理 (VP) 强制访问者登录并通过 IdP(例如上面列出的服务之一)进行身份验证,然后才允许他们访问网站。
VP 还可以用作单点登录 (SSO) 解决方案来保护同一域中的所有 Web 应用程序。
访问者登录后,Vouch Proxy 允许在几个小时内访问受保护的网站。每个请求都会由 VP 检查以确保其有效。
VP 可以将 IdP 提供的访问者的电子邮件、姓名和其他信息(包括访问令牌)作为 HTTP 标头发送到 Web 应用程序。 VP可以用来完全取代应用程序的用户管理。
Vouch Proxy 依赖于在 Vouch Proxy 服务器与其保护的应用程序之间共享 cookie 的能力。通常,这可以通过在子域(例如vouch.yourdomain.com
上运行 Vouch 来完成,并且应用程序在app1.yourdomain.com
和app2.yourdomain.com
上运行。受保护的域是.yourdomain.com
,并且必须在此域中设置 Vouch 代理 cookie,方法是将 vouch.domains 设置为包含yourdomain.com
,或者有时将 vouch.cookie.domain 设置为yourdomain.com
。
cp ./config/config.yml_example_$OAUTH_PROVIDER ./config/config.yml
在 google 或 github 等处为 Vouch Proxy 创建 OAuth 凭据
请务必将回调 URL 定向到 Vouch Proxy /auth
端点
配置 Nginx...
以下 Nginx 配置假设..
Nginx、 vouch.yourdomain.com
和protectedapp.yourdomain.com
在同一服务器上运行
两个域都作为https
提供服务并具有有效的证书(如果没有,请更改为listen 80
并将 vouch.cookie.secure 设置为false
)
服务器 { 监听 443 ssl http2; 服务器名称 protectedapp.yourdomain.com; 根/var/www/html/; ssl_certificate /etc/letsencrypt/live/protectedapp.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/protectedapp.yourdomain.com/privkey.pem; # 将所有请求发送到“/validate”端点进行授权 auth_request /validate; location = /validate { # 将 /validate 请求转发到 Vouch Proxy proxy_pass http://127.0.0.1:9090/validate; # 一定要传入原始主机头 proxy_set_header Host $http_host; # Vouch Proxy 仅作用于请求标头 proxy_pass_request_body off; proxy_set_header 内容长度 ""; # 可选择添加 Vouch 代理返回的 X-Vouch-User 以及请求 auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user; # 可选择添加您正在跟踪的 X-Vouch-IdP-Claims-* 自定义声明 # auth_request_set $auth_resp_x_vouch_idp_claims_groups $upstream_http_x_vouch_idp_claims_groups; # auth_request_set $auth_resp_x_vouch_idp_claims_given_name $upstream_http_x_vouch_idp_claims_given_name; # 可选择添加 X-Vouch-IdP-AccessToken 或 X-Vouch-IdP-IdToken # auth_request_set $auth_resp_x_vouch_idp_accesstoken $upstream_http_x_vouch_idp_accesstoken; # auth_request_set $auth_resp_x_vouch_idp_idtoken $upstream_http_x_vouch_idp_idtoken; # 这些返回值由 @error401 调用 auth_request_set 使用 $auth_resp_jwt $upstream_http_x_vouch_jwt; auth_request_set $auth_resp_err $upstream_http_x_vouch_err; auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount; # Vouch Proxy 可以在同一个 Nginx 反向代理后面运行 # 可能需要遵守“上游”服务器命名 # proxy_pass http://vouch.yourdomain.com/validate; # proxy_set_header 主机 $http_host; } # 如果 validate 返回 `401 notauthorized`,则将请求转发到 error401 块 error_page 401 = @error401; location @error401 { # 重定向到 Vouch 代理进行登录 return 302 https://vouch.yourdomain.com/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$ auth_resp_err; # 你通常*想要*重定向到在受 https 保护的同一个 Nginx 配置后面运行的 Vouch # 但要开始,你可以将最终用户转发到 vouch 正在运行的端口 # return 302 http://vouch.yourdomain.com:9090/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err; } location / { # 将授权请求转发到您的服务 protectedapp.yourdomain.com proxy_pass http://127.0.0.1:8080; # 您可能需要按照 https://github.com/vouch/vouch-proxy/issues/26#issuecomment-425215810 在此块中设置这些变量 # auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user # auth_request_set $auth_resp_x_vouch_idp_claims_groups $upstream_http_x_vouch_idp_claims_groups; # auth_request_set $auth_resp_x_vouch_idp_claims_given_name $upstream_http_x_vouch_idp_claims_given_name; # 设置用户标头(通常是电子邮件) proxy_set_header X-Vouch-User $auth_resp_x_vouch_user; # 有选择地传递您正在跟踪的任何自定义声明 # proxy_set_header X-Vouch-IdP-Claims-Groups $auth_resp_x_vouch_idp_claims_groups; # proxy_set_header X-Vouch-IdP-Claims-Given_Name $auth_resp_x_vouch_idp_claims_given_name; # 可选地传递 accesstoken 或 idtoken # proxy_set_header X-Vouch-IdP-AccessToken $auth_resp_x_vouch_idp_accesstoken; # proxy_set_header X-Vouch-IdP-IdToken $auth_resp_x_vouch_idp_idtoken; } }
如果在同一个nginx 反向代理后面配置了 Vouch(也许可以配置 ssl),请确保正确传递Host
标头,否则无法将 JWT cookie 设置到域中
服务器 { 监听 443 ssl http2; 服务器名称 vouch.yourdomain.com; ssl_certificate /etc/letsencrypt/live/vouch.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/vouch.yourdomain.com/privkey.pem; 位置/{ proxy_pass http://127.0.0.1:9090; # 一定要传入原始主机头 proxy_set_header Host $http_host; } }
从v0.33.0
开始,可以通过配置vouch.document_root: /vp_in_a_path
这样就无需为 Vouch Proxy 设置单独的域,例如vouch.yourdomain.com
。例如,VP 登录将从https://protectedapp.yourdomain.com/vp_in_a_path/login
提供
服务器 { 监听 443 ssl http2; 服务器名称 protectedapp.yourdomain.com; ssl_certificate /etc/letsencrypt/live/protectedapp.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/protectedapp.yourdomain.com/privkey.pem; # 此位置为所有 Vouch 代理端点提供 /vp_in_a_path/$uri # 包括 /vp_in_a_path/validate、/vp_in_a_path/login、/vp_in_a_path/logout、/vp_in_a_path/auth、/vp_in_a_path/auth/$STATE 等 location /vp_in_a_path { proxy_pass http://127.0.0.1:9090; #一定不能! proxy_set_header 末尾有一个斜线 Host $http_host; proxy_pass_request_body 关闭; proxy_set_header 内容长度 ""; # 这些返回值由 @error401 调用 auth_request_set 使用 $auth_resp_jwt $upstream_http_x_vouch_jwt; auth_request_set $auth_resp_err $upstream_http_x_vouch_err; auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount; } # 如果 /vp_in_a_path/validate 返回 `401 notauthorized`,则将请求转发到 error401 块 error_page 401 = @error401; location @error401 { # 重定向到 Vouch 代理进行登录 return 302 https://protectedapp.yourdomain.com/vp_in_a_path/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error =$auth_resp_err; } 位置 / { auth_request /vp_in_a_path/validate; proxy_pass http://127.0.0.1:8080; # 请参阅上面的 Nginx 配置,了解可以从 Vouch Proxy 设置的其他标头 } }
其他 Nginx 配置可以在示例目录中找到。
这是使用 Google 的 OAuth 的最小设置...
VOUCH_DOMAINS=yourdomain.com OAUTH_PROVIDER=谷歌 OAUTH_CLIENT_ID=1234 OAUTH_CLIENT_SECRET=秘密秘密 OAUTH_CALLBACK_URL=https://vouch.yourdomain.com/auth ./凭证代理
环境变量名称记录在 config/config.yml_example 中
所有具有多个值的列表都必须以逗号分隔: VOUCH_DOMAINS="yourdomain.com,yourotherdomain.com"
变量VOUCH_CONFIG
可用于设置配置文件的备用位置。 VOUCH_ROOT
可用于设置 Vouch Proxy 的备用根目录以查找支持文件。
所有 Vouch Proxy 配置项都记录在 config/config.yml_example 中
在 Nginx 中缓存 Vouch 代理/validate
响应
使用 Vouch 代理保护 API 时处理OPTIONS
请求
由 GitHub 团队或 GitHub Org 进行验证
使用基于 ARM 的 Docker 映像在 Raspberry Pi 上运行 VP
Kubernetes 架构后入口
设置HTTP_PROXY
以通过出站代理服务器中继 Vouch Proxy IdP 请求
Google Cloud Run 服务的反向代理
在 Vouch Proxy 中启用本机 TLS
FreeBSD 支持
Vouch Proxy 的systemd
启动
使用 Node.js 而不是 Nginx 来路由请求
开发单页应用程序 (SPA),同时使用受 VP 保护的 API
将 Vouch Proxy 集成到服务器端应用程序中以进行用户 Authn 和 Authz
在 VP 验证之前使用satisfy any;
请帮助我们扩展此列表。
使用 Vouch Proxy,您可以请求各种scopes
(标准和自定义)以获取有关用户的更多信息或访问提供商的 API。在内部,Vouch Proxy 在身份验证成功后向user_info_url
发起请求。所需的claims
从提供商的响应中提取并存储在 VP cookie 中。
VP cookie 可以分为多个 cookie,以适应浏览器 cookie 大小限制。但如果你需要它,你就需要它。大的 cookie 和标头需要 Nginx 配置更大的缓冲区。有关详细信息,请参阅 large_client_header_buffers 和 proxy_buffer_size。
scopes
和claims
正常配置 Nginx 的 Vouch 代理和 IdP(请参阅:安装和配置)
在 vouch-proxy config.yml
的oauth
部分设置必要的scope
(示例配置)
在 vouch-proxy 的config.yml
的headers
部分设置idtoken: X-Vouch-IdP-IdToken
在现代浏览器中登录并调用/validate
端点
检查响应标头中的X-Vouch-IdP-IdToken
标头
将标头的值复制到 https://jwt.io/ 的调试器中,并确保必要的声明是 jwt 的一部分
如果不是,您需要调整config.yml
的oauth
部分中的scopes
或重新配置您的 oauth 提供程序
在 vouch-proxy config.yml
的header
部分中设置必要的claims
在现代浏览器中登录并调用/validate
端点
检查响应标头中是否存在X-Vouch-IdP-Claims-<ClaimName>
形式的标头
如果它们不存在,请清除您的 cookie 和缓存的浏览器数据
?如果它们仍然不存在但存在于 jwt 中(尤其是自定义声明),则可能存在错误
如果不需要,请从 vouch-proxy 的config.yml
的headers
部分中删除idtoken: X-Vouch-IdP-IdToken
在 nginx server.conf
中受保护位置内的auth_request
之后使用auth_request_set
使用声明(示例 nginx 配置)
docker运行-d -p 9090:9090 --名称验证代理 -v ${PWD}/config:/config quay.io/vouch/vouch-proxy
或者
docker运行-d -p 9090:9090 --名称验证代理 -e VOUCH_DOMAINS=yourdomain.com -e OAUTH_PROVIDER=谷歌 -e OAUTH_CLIENT_ID=1234 -e OAUTH_CLIENT_SECRET=秘密秘密 -e OAUTH_CALLBACK_URL=https://vouch.yourdomain.com/auth quay.io/vouch/vouch-proxy
从v0.36.0
开始,容器中的 docker 进程以 UID 999 和 GID 999 的用户vouch
身份运行。您可能需要设置/config/config.yml
和/config/secret
的权限以对应于该用户可读,或者使用docker run --user $UID:$GID ...
或者从源代码构建 docker 容器并使用 UID 和 GID 的可用 ARG。
quay.io 提供每个 Vouch Proxy 版本的自动化容器构建。每个版本都会产生..
从Dockerfile
构建的最小 go 二进制容器
quay.io/vouch/vouch-proxy:latest
quay.io/vouch/vouch-proxy:xyz
例如quay.io/vouch/vouch-proxy:0.28.0
从Dockerfile.alpine
构建的基于alpine
的容器
quay.io/vouch/vouch-proxy:alpine-latest
quay.io/vouch/vouch-proxy:alpine-xyz
Docker Hub 上提供了 Vouch Proxy arm
镜像
voucher/vouch-proxy:latest-arm
如果您将 kubernetes 与 nginx-ingress 结合使用,则可以使用以下注释配置您的 ingress(注意引用auth-signin
注释):
nginx.ingress.kubernetes.io/auth-signin:“https://vouch.yourdomain.com/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$ auth_resp_err” nginx.ingress.kubernetes.io/auth-url:https://vouch.yourdomain.com/validate nginx.ingress.kubernetes.io/auth-response-headers:X-Vouch-User nginx.ingress.kubernetes.io/auth-snippet:| # 这些返回值由@error401调用使用 auth_request_set $auth_resp_jwt $upstream_http_x_vouch_jwt; auth_request_set $auth_resp_err $upstream_http_x_vouch_err; auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount; # 当 VP 托管在 k8s 外部时,确保 SSL 证书有效以避免 MITM 风险 # proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; # proxy_ssl_session_reuse 开启; # proxy_ssl_verify_深度 2; # proxy_ssl_verify 开启;
Helm Charts 由 punkle、martina-if 和 halkeye 维护,可在 https://github.com/vouch/helm-charts 上获取
./do.sh 戈吉特 ./do.sh 构建 ./凭证代理
从v0.29.0
开始, .defaults.yml
中的所有模板、静态资源和配置默认值均使用 go:embed 指令构建到静态二进制文件中。
从v0.11.0
开始,附加检查已到位,以减少 url 重定向的攻击面。
传递的网址...
必须以http
或https
开头
必须与vouch.domains
列表或vouch.cookie.domain
中的域重叠(如果配置了其中任何一个)
不能有包含 URL 的参数以防止 URL 链接攻击
Vouch 代理/logout
端点接受查询字符串中的url
参数,该参数可用于将用户302
重定向到原始 OAuth 提供商/IDP/OIDC 提供商的 revotion_endpoint
https://vouch.oursites.com/logout?url=https://oauth2.googleapis.com/revoke
此 url 必须存在于配置文件列表vouch.post_logout_redirect_uris
中
# 为了防止重定向攻击,必须指定所有重定向到 /logout 的 URL# 该 URL 仍必须以 https://vouch.yourdomain.com/logout?url=${ONE OF THE URLS BELOW}post_logout_redirect_uris 形式传递到 Vouch 代理: # 您的应用程序登录页面 - https://yourdomain.com/login # 您的 IdP 注销点 # 来自 https://accounts.google.com/.well-known/openid-configuration - https://oauth2.googleapis.com/revoke # 您可能通过菊花链连接到您的 IdP - https://myorg.okta.com/oauth2/123serverid/v1/logout?post_logout_redirect_uri=http://myapp.yourdomain.com/login
请注意,您的 IdP 可能会携带自己的单独的post_logout_redirect_uri
列表。
注销资源..
谷歌
奥克塔
验证0
让 Nginx、Vouch Proxy 和 IdP 之间的协调一致可能很棘手。我们希望帮助您尽快启动并运行。最常见的问题是..
仔细检查您是否在可以共享 cookie 的公共域上运行 Vouch Proxy 和您的应用程序。例如, vouch.yourdomain.com
和app.yourdomain.com
可以共享.yourdomain.com
域上的 Cookie。 (如果您尝试使用vouch.yourdomain.org
和app.yourdomain.net
,它将不起作用。)
您可能需要显式定义应设置 cookie 的域。您可以通过设置选项在配置文件中执行此操作:
vouch: cookie: # 强制cookie的域设置domain: yourdomain.com
如果您仍然遇到问题,请尝试以下操作:
打开vouch.testing: true
。这会减慢循环速度。
设置vouch.logLevel: debug
。
http 请求中的Host:
标头、 oauth.callback_url
和配置的vouch.domains
必须全部对齐,以便携带 JWT 的 cookie 可以正确放置到浏览器中,然后在每个请求中返回
像饼干一样思考会很有帮助。
cookie 被设置到域中。如果您的siteA.yourdomain.com
和siteB.yourdomain.com
受 Vouch Proxy 保护,您希望将 Vouch Proxy cookie 设置到.yourdomain.com
如果您通过vouch.yourdomain.com
进行身份验证,则dev.anythingelse.com
将无法看到 cookie
除非您使用 https,否则应该设置vouch.cookie.secure: false
cookie可用于域的所有端口
请查看已关闭的提及重定向的问题
请按以下方式提交新问题。
总而言之:
设置vouch.testing: true
设置vouch.logLevel: debug
进行两次完整的往返./vouch-proxy
捕获输出..
副总裁启动
/validate
/login
- 即使错误就在这里
/auth
/validate
- 捕获一切
将所有日志和配置放在gist
中。
./do.sh bug_report
是你的朋友
打开vouch.testing: true
并设置vouch.logLevel: debug
。
使用要点或其他粘贴服务,例如 hasteb.in。不要将您的日志和配置放入 GITHUB 问题中。使用粘贴服务很重要,因为它将保持间距并提供行号和格式。我们正在大海捞针,设置有多个移动部件,这些功能有很大帮助。粘贴服务可以节省您和我们的时间,并帮助我们快速为您提供帮助。遵循此建议,您更有可能及时从我们那里获得良好的支持。
运行./do.sh bug_report secretdomain.com secretpass [anothersecret..]
这将创建配置的编辑版本并记录删除每个字符串
并按照最后的说明编辑 Nginx 配置
所有这些都有一个要点
然后在此存储库中打开一个新问题
可以使用quay.io/vouch/vouch-proxy:alpine
图像从 docker 环境生成错误报告...
docker run --name vouch_proxy -v $PWD/config:/config -v $PWD/certs:/certs -it --rm --entrypoint /do.sh quay.io/vouch/vouch-proxy:alpine bug_report yourdomain.com anotherdomain.com someothersecret
我们很乐意您做出贡献!详情请参阅我们的贡献指南。
OpenResty® 是一个成熟的 Web 平台,集成了标准的 Nginx 核心、LuaJIT、许多精心编写的 Lua 库、大量高质量的第 3 方 Nginx 模块及其大部分外部依赖项。
您可以相当轻松地用 OpenResty 替换 nginx。
借助 OpenResty 和 Lua,可以对任何标头或声明凭证传递提供定制和高级授权。
示例目录中提供了 OpenResty 和各种场景的配置。
鲍勃访问https://private.oursites.com
Nginx 反向代理...
如果/validate
返回...
通过 302 重定向到https://vouch.oursites.com/login?url=https://private.oursites.com
来响应 Bob
200 OK then SUCCESS 允许鲍勃通过
401 则未授权
收到 Bob 发送的 private.oursites.com 请求
使用为/validate
路径配置的auth_request
模块
/validate
配置为将proxy_pass
请求发送到https://vouch.oursites.com/validate
的身份验证服务
凭证代理https://vouch.oursites.com/validate
返回401 NotAuthorized
给 Nginx(将请求转发到登录)
返回200 OK
给 Nginx,这将允许访问(鲍勃什么也没注意到)
通过 Nginx proxy_pass
接收来自 Bob 的 private.oursites.com 请求
查找名为“oursitesSSO”的 cookie,其中包含 JWT
如果找到 cookie,并且 JWT 有效
如果未找到 cookie,或者 JWT 无效
Bob 首先被简短转发到https://vouch.oursites.com/login?url=https://private.oursites.com
清除名为“oursitesSSO”的 cookie(如果存在)
生成一个随机数并将其存储在会话变量 $STATE 中
将查询字符串中的 url https://private.oursites.com
存储在会话变量$requestedURL
中
通过 302 重定向到 Google 的 OAuth 登录表单来响应 Bob,包括$STATE
随机数
Bob 使用 Oauth 登录他的 Google 帐户
登录成功后
Google 通过 302 重定向到https://vouch.oursites.com/auth?state=$STATE
来响应 Bob
Bob 被转发到https://vouch.oursites.com/auth?state=$STATE
以名为“oursitesSSO”的 cookie 形式向 bob 发出 JWT
检索会话变量$requestedURL
并将 bob 302 重定向回https://private.oursites.com
如果 url 中的 $STATE 随机数与会话变量“state”匹配
向 Google(服务器到服务器)发出“第三条腿”请求,以交换 Bob 的用户信息(包括电子邮件地址 [email protected])的 OAuth 代码
如果电子邮件地址与 oursites.com 域匹配(确实如此)
请注意,除了一些无害的重定向之外,Bob 只能在浏览器中看到https://private.oursites.com
和 Google 登录屏幕。虽然 Vouch 确实与 Bob 的浏览器进行了多次交互,但这只是为了设置 cookie,如果 302 重定向工作正常,Bob 将快速登录。
设置 JWT 后,Bob 将被授权访问配置为使用auth_request
Nginx 模块中的https://vouch.oursites.com/validate
的所有其他站点。
下次 Bob 被转发到 google 进行登录时,由于他已经授权了 Vouch Proxy OAuth 应用程序,Google 会立即将他转发回来并设置 cookie 并让他继续他的快乐之路。在某些浏览器(例如 Chrome)中,Bob 甚至可能没有注意到他使用 Vouch Proxy 登录。