diff --git a/apisix/plugins/openid-connect.lua b/apisix/plugins/openid-connect.lua index 8ed6ab4447ef..a64ba2fa9122 100644 --- a/apisix/plugins/openid-connect.lua +++ b/apisix/plugins/openid-connect.lua @@ -440,6 +440,8 @@ function _M.rewrite(plugin_conf, ctx) conf.timeout = conf.timeout * 1000 end + local path = ctx.var.request_uri + if not conf.redirect_uri then -- NOTE: 'lua-resty-openidc' requires that 'redirect_uri' be -- different from 'uri'. So default to append the @@ -464,6 +466,19 @@ function _M.rewrite(plugin_conf, ctx) conf.ssl_verify = "no" end + if path == (conf.logout_path or "/logout") then + local discovery, discovery_err = openidc.get_discovery_doc(conf) + if discovery_err then + core.log.error("OIDC access discovery url failed : ", discovery_err) + return 503 + end + if conf.post_logout_redirect_uri and not discovery.end_session_endpoint then + -- If the end_session_endpoint field does not exist in the OpenID Provider Discovery + -- Metadata, the redirect_after_logout_uri field is used for redirection. + conf.redirect_after_logout_uri = conf.post_logout_redirect_uri + end + end + local response, err, session, _ if conf.bearer_only or conf.introspection_endpoint or conf.public_key then diff --git a/docs/en/latest/plugins/openid-connect.md b/docs/en/latest/plugins/openid-connect.md index 23b50906c296..99f4d980028a 100644 --- a/docs/en/latest/plugins/openid-connect.md +++ b/docs/en/latest/plugins/openid-connect.md @@ -43,7 +43,7 @@ description: OpenID Connect allows the client to obtain user information from th | realm | string | False | "apisix" | | Realm used for authentication. | | bearer_only | boolean | False | false | | When set to `true`, APISIX will only check if the authorization header in the request matches a bearer token. | | logout_path | string | False | "/logout" | | Path for logging out. | -| post_logout_redirect_uri | string | False | | | URL to redirect to after logging out. | +| post_logout_redirect_uri | string | False | | | URL to redirect to after logging out. If the OIDC discovery endpoint does not provide an [`end_session_endpoint`](https://openid.net/specs/openid-connect-rpinitiated-1_0.html), the plugin internally redirects using the [`redirect_after_logout_uri`](https://github.com/zmartzone/lua-resty-openidc). Otherwise, it redirects using the [`post_logout_redirect_uri`](https://openid.net/specs/openid-connect-rpinitiated-1_0.html). | | redirect_uri | string | False | | | URI to which the identity provider redirects back to. If not configured, APISIX will append the `.apisix/redirect` suffix to determine the default `redirect_uri`. Note that the provider should be properly configured to allow such `redirect_uri` values. | | timeout | integer | False | 3 | [1,...] | Request timeout time in seconds. | | ssl_verify | boolean | False | false | | When set to true, verifies the identity provider's SSL certificates. | diff --git a/docs/zh/latest/plugins/openid-connect.md b/docs/zh/latest/plugins/openid-connect.md index 3ae3fe3569e1..9c5f18b43064 100644 --- a/docs/zh/latest/plugins/openid-connect.md +++ b/docs/zh/latest/plugins/openid-connect.md @@ -42,7 +42,7 @@ description: OpenID Connect(OIDC)是基于 OAuth 2.0 的身份认证协议 | realm | string | 否 | "apisix" | | bearer token 无效时 [`WWW-Authenticate` 响应头](https://www.rfc-editor.org/rfc/rfc6750#section-3)中会伴随着的 `realm` 讯息。 | | bearer_only | boolean | 否 | false | | 当设置为 `true` 时,将仅检查请求头中的令牌(Token)。 | | logout_path | string | 否 | "/logout" | | 登出路径。 | -| post_logout_redirect_uri | string | 否 | | | 调用登出接口后想要跳转的 URL。 | +| post_logout_redirect_uri | string | 否 | | | 调用登出接口后想要跳转的 URL。如果 OIDC 的服务发现端点没有提供 [`end_session_endpoint`](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) ,插件内部会使用 [`redirect_after_logout_uri`](https://github.com/zmartzone/lua-resty-openidc) 进行重定向,否则使用 [`post_logout_redirect_uri`](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) 进行重定向。 | | redirect_uri | string | 否 | | | 身份提供者重定向返回的 URI。如果缺失,则 APISIX 将在当前 URI 之后追加 `.apisix/redirect` 作为默认的 `redirect_uri`。注意,OP 也需要适当配置以允许这种形式的 `redirect_uri`。 | | timeout | integer | 否 | 3 | [1,...] | 请求超时时间,单位为秒 | | ssl_verify | boolean | 否 | false | [true, false] | 当设置为 `true` 时,验证身份提供者的 SSL 证书。 | diff --git a/t/plugin/openid-connect.t b/t/plugin/openid-connect.t index a62ef771b923..f539a5fba8d4 100644 --- a/t/plugin/openid-connect.t +++ b/t/plugin/openid-connect.t @@ -1303,3 +1303,125 @@ passed } --- response_body_like x-userinfo: ey.* + + + +=== TEST 34: Set up new route with plugin matching URI `/*` +--- 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", + "post_logout_redirect_uri": "https://iresty.com", + "scope": "openid profile" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/*" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- response_body +passed + + + +=== TEST 35: Check whether auth0 can redirect normally using post_logout_redirect_uri configuration +--- 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 .. "/logout" + 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://iresty.com') ~= -1 and + string.find(location, 'post_logout_redirect_uri=https://iresty.com') ~= -1 then + ngx.say(true) + end + } + } +--- timeout: 10s +--- response_body +true +--- error_code: 302 + + + +=== TEST 36: Set up new route with plugin matching URI `/*` +--- 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": "942299072001-vhduu1uljmdhhbbp7g22m3qsmo246a75.apps.googleusercontent.com", + "client_secret": "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", + "discovery": "https://accounts.google.com/.well-known/openid-configuration", + "redirect_uri": "https://iresty.com", + "post_logout_redirect_uri": "https://iresty.com", + "scope": "openid profile" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/*" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- response_body +passed + + + +=== TEST 37: Check whether google can redirect normally using post_logout_redirect_uri configuration +--- 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 .. "/logout" + 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://iresty.com') ~= -1 and + string.find(location, 'post_logout_redirect_uri=https://iresty.com') ~= -1 then + ngx.say(true) + end + } + } +--- timeout: 10s +--- response_body +true +--- error_code: 302