diff --git a/apisix/plugins/openid-connect.lua b/apisix/plugins/openid-connect.lua index 5058eba47d28..927e4ddbd8aa 100644 --- a/apisix/plugins/openid-connect.lua +++ b/apisix/plugins/openid-connect.lua @@ -130,6 +130,32 @@ local schema = { "header to the request for downstream.", type = "boolean", default = false + }, + proxy_opts = { + description = "HTTP proxy server be used to access identity server.", + type = "object", + properties = { + http_proxy = { + type = "string", + description = "HTTP proxy like: http://proxy-server:80.", + }, + https_proxy = { + type = "string", + description = "HTTPS proxy like: http://proxy-server:80.", + }, + http_proxy_authorization = { + type = "string", + description = "Basic [base64 username:password].", + }, + https_proxy_authorization = { + type = "string", + description = "Basic [base64 username:password].", + }, + no_proxy = { + type = "string", + description = "Comma separated list of hosts that should not be proxied.", + } + }, } }, encrypt_fields = {"client_secret"}, diff --git a/docs/en/latest/plugins/openid-connect.md b/docs/en/latest/plugins/openid-connect.md index a5e015089d40..493370240362 100644 --- a/docs/en/latest/plugins/openid-connect.md +++ b/docs/en/latest/plugins/openid-connect.md @@ -61,6 +61,12 @@ description: OpenID Connect allows the client to obtain user information from th | session | object | False | | | When bearer_only is set to false, openid-connect will use Authorization Code flow to authenticate on the IDP, so you need to set the session-related configuration. | | session.secret | string | True | Automatic generation | 16 or more characters | The key used for session encrypt and HMAC operation. | | unauth_action | string | False | "auth" | | Specify the response type on unauthenticated requests. "auth" redirects to identity provider, "deny" results in a 401 response, "pass" will allow the request without authentication. | +| proxy_opts | object | False | | | HTTP proxy server be used to access identity server. | +| proxy_opts.proxy_opts.http_proxy | string | False | | http://proxy-server:port | HTTP proxy server address. | +| proxy_opts.proxy_opts.https_proxy | string | False | | http://proxy-server:port | HTTPS proxy server address. | +| proxy_opts.http_proxy_authorization | string | False | | Basic [base64 username:password] | Default `Proxy-Authorization` header value to be used with `http_proxy`. | +| proxy_opts.https_proxy_authorization | string | False | | Basic [base64 username:password] | As `http_proxy_authorization` but for use with `https_proxy` (since with HTTPS the authorisation is done when connecting, this one cannot be overridden by passing the `Proxy-Authorization` request header). | +| proxy_opts.no_proxy | string | False | | | Comma separated list of hosts that should not be proxied. | NOTE: `encrypt_fields = {"client_secret"}` is also defined in the schema, which means that the field will be stored encrypted in etcd. See [encrypted storage fields](../plugin-develop.md#encrypted-storage-fields). diff --git a/docs/zh/latest/plugins/openid-connect.md b/docs/zh/latest/plugins/openid-connect.md index c914f5241511..aececc4986e0 100644 --- a/docs/zh/latest/plugins/openid-connect.md +++ b/docs/zh/latest/plugins/openid-connect.md @@ -60,6 +60,13 @@ description: OpenID Connect(OIDC)是基于 OAuth 2.0 的身份认证协议 | set_refresh_token_header | boolean | 否 | false | | 当设置为 `true` 并且刷新令牌可用时,则会将该属性设置在`X-Refresh-Token`请求头中。 | | session | object | 否 | | | 当设置 bearer_only 为 false 时,openid-connect 插件将使用 Authorization Code 在 IDP 上进行认证,因此你必须设置 session 相关设置。 | | session.secret | string | 是 | 自动生成 | 16 个以上字符 | 用于 session 加密和 HMAC 计算的密钥。 | +| proxy_opts | object | 否 | | | 给 openid-connect 插件配置一个 proxy。 | +| proxy_opts | object | 否 | | | 用来访问身份认证服务器的代理服务器。 | +| proxy_opts.proxy_opts.http_proxy | string | 否 | | http://proxy-server:port | HTTP 代理服务器地址。 | +| proxy_opts.proxy_opts.https_proxy | string | 否 | | http://proxy-server:port | HTTPS 代理服务器地址。 | +| proxy_opts.http_proxy_authorization | string | 否 | | Basic [base64 username:password] | `http_proxy` 默认的 `Proxy-Authorization` 请求头参数值。 | +| proxy_opts.https_proxy_authorization | string | 否 | | Basic [base64 username:password] | 与`http_proxy_authorization`相同,但与`https_proxy`一起使用(因为使用 HTTPS 时,授权是在连接时完成的,因此不能通过传递 Proxy-Authorization 请求头来覆盖此授权)。 | +| proxy_opts.no_proxy | string | 否 | | | 不应被代理的主机的逗号分隔列表。 | 注意:schema 中还定义了 `encrypt_fields = {"client_secret"}`,这意味着该字段将会被加密存储在 etcd 中。具体参考 [加密存储字段](../plugin-develop.md#加密存储字段)。 diff --git a/t/plugin/openid-connect3.t b/t/plugin/openid-connect3.t new file mode 100644 index 000000000000..84eb7c26de2b --- /dev/null +++ b/t/plugin/openid-connect3.t @@ -0,0 +1,111 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +use t::APISIX 'no_plan'; + +log_level('debug'); +repeat_each(1); +no_long_string(); +no_root_location(); +no_shuffle(); + +add_block_preprocessor(sub { + my ($block) = @_; + + if ((!defined $block->error_log) && (!defined $block->no_error_log)) { + $block->set_value("no_error_log", "[error]"); + } + + if (!defined $block->request) { + $block->set_value("request", "GET /t"); + } +}); + +run_tests(); + +__DATA__ + +=== TEST 1: Set up new route access the auth server via http proxy +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "openid-connect": { + "client_id": "kbyuFDidLLm280LIwVFiazOqjO3ty8KH", + "client_secret": "60Op4HFM0I8ajz0WdiStAbziZ-VFQttXuxixHHs2R7r7-CW8GR79l-mmLqMhc-Sa", + "discovery": "https://samples.auth0.com/.well-known/openid-configuration", + "redirect_uri": "https://iresty.com", + "ssl_verify": false, + "timeout": 10, + "scope": "apisix", + "proxy_opts": { + "http_proxy": "http://127.0.0.1:8080", + "http_proxy_authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQK" + }, + "use_pkce": false + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + + } + } +--- response_body +passed + + + +=== TEST 2: Access route w/o bearer token. Should redirect to authentication endpoint of ID provider. +--- config + location /t { + content_by_lua_block { + local http = require "resty.http" + local httpc = http.new() + local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello" + local res, err = httpc:request_uri(uri, {method = "GET"}) + ngx.status = res.status + local location = res.headers['Location'] + if location and string.find(location, 'https://samples.auth0.com/authorize') ~= -1 and + string.find(location, 'scope=apisix') ~= -1 and + string.find(location, 'client_id=kbyuFDidLLm280LIwVFiazOqjO3ty8KH') ~= -1 and + string.find(location, 'response_type=code') ~= -1 and + string.find(location, 'redirect_uri=https://iresty.com') ~= -1 then + ngx.say(true) + end + } + } +--- timeout: 10s +--- response_body +true +--- error_code: 302 +--- error_log +use http proxy