apisix icon indicating copy to clipboard operation
apisix copied to clipboard

bug:enable openid-connect plugin without redirect_uri got 500 error

Open liuxiran opened this issue 5 years ago • 43 comments

Please answer these questions before submitting your issue.

  • Why do you submit this issue?
  • [ ] Question or discussion
  • [x] Bug
  • [ ] Requirements
  • [ ] Feature or performance improvement
  • [ ] Other

Bug

  • Which version of Apache APISIX Dashboard, OS, and Browser?
  1. create a route, enable openid-connect plugin, configs:
{
	"name": "api2",
	"route_group_id": "de45ec14-317f-4177-8a22-10ab95bd45f7",
	"route_group_name": "group1",
	"status": true,
	"desc": "",
	"protocols": ["http"],
	"paths": ["/get1"],
	"methods": ["GET"],
	"upstream_protocol": "https",
	"type": "roundrobin",
	"plugins": {
		"openid-connect": {
			"client_id": "kbyuFDidLLm280LIwVFiazOqjO3ty8KH",
			"client_secret": "60Op4HFM0I8ajz0WdiStAbziZ-VFQttXuxixHHs2R7r7-CW8GR79l-mmLqMhc-Sa",
			"discovery": "https://samples.auth0.com/.well-known/openid-configuration"
		}
	},
	"script": {},
	"uris": ["/get1"],
	"vars": [],
	"upstream": {
		"type": "roundrobin",
		"nodes": {
			"httpbin.org:443": 1
		},
		"timeout": {
			"connect": 6000,
			"send": 6000,
			"read": 6000
		}
	},
	"upstream_header": {},
	"upstream_path": {
		"to": "/get"
	}
}
  1. visit this route via chrome, got 500 error

2020-10-10 14-52-43屏幕截图

  1. got the error log in apisix error.log:
2020/10/10 06:47:45 [error] 26#26: *6045490 [lua] openidc.lua:1378: authenticate(): request to the redirect_uri path but there's no session state found, client: 192.168.1.145, server: , request: "GET /get HTTP/1.1", host: "192.168.1.145:9
2020/10/10 06:47:45 [error] 26#26: *6045490 [lua] openid-connect.lua:163: phase_func(): failed to authenticate in openidc: request to the redirect_uri path but there's no session state found, client: 192.168.1.145, server: , request: "GET
2020/10/10 06:47:45 [error] 25#25: *6045493 lua entry thread aborted: runtime error: /usr/local/apisix/apisix/plugins/echo.lua:96: attempt to index local 'conf' (a userdata value)
stack traceback:                                                                                                                                            
coroutine 0:                                                                                                                                             
        /usr/local/apisix/apisix/plugins/echo.lua: in function 'phase_fun'                                                                                     
        [string "route#41ee9eef-564e-4208-86e6-fc6834bd7178"]:17: in function 'phase_func'                                                                  
        /usr/local/apisix/apisix/script.lua:52: in function 'run'                                                                                                 
        /usr/local/apisix/apisix/init.lua:508: in function 'http_access_phase'                                                                                 
        access_by_lua(nginx.conf:173):2: in main chunk, client: 192.168.1.145, server: , request: "GET /favicon.ico HTTP/1.1", host: "192.168.1.145:9080", referrer: "http://192.168.1.145:9080/get"

redirect_uri should be a reqired param in openid-connect plugin

liuxiran avatar Oct 10 '20 09:10 liuxiran

Here is the doc for openid-connect, cc @membphis

https://github.com/apache/apisix/blob/master/doc/plugins/openid-connect.md

juzhiyuan avatar Oct 10 '20 14:10 juzhiyuan

@nic-chen need your help to confirm a mini case

membphis avatar Oct 11 '20 01:10 membphis

This issue is related to apisix according to @nic-chen's feedback, so I transfer it here.

juzhiyuan avatar Oct 15 '20 02:10 juzhiyuan

@membphis

I think it's a schema defined bug. redirect_uri should be required according to the error log.

@liuxiran Could you solve it together, please? It looks like you are solving issues of other plugins's schema 😄

https://github.com/apache/apisix/blob/master/apisix/plugins/openid-connect.lua#L45

nic-chen avatar Oct 16 '20 15:10 nic-chen

I think it's a schema defined bug. redirect_uri should be required according to the error log.

A new PR to fix this bug is better. welcome PR

membphis avatar Oct 17 '20 14:10 membphis

@nic-chen If redirect_uri is not provided in schema, it will be set by ngx.var.request_uri, please see openid-connect.lua, Dose this mean that request_uri already has a default value, request_uri should be optional? Looking forward to your reply, thx

fukiki avatar Oct 19 '20 11:10 fukiki

@nic-chen @membphis ping

moonming avatar Oct 21 '20 09:10 moonming

@moonming Please confirm which way is correct. You wrote this code.

  1. if the redirect_uri is a required field.
  2. if not, what is the default value? ctx.var.request_uri?

https://github.com/apache/apisix/blob/master/apisix/plugins/openid-connect.lua#L143-L146

membphis avatar Oct 21 '20 09:10 membphis

yes, redirect_uri is optional

moonming avatar Oct 21 '20 10:10 moonming

2020/10/10 06:47:45 [error] 26#26: *6045490 [lua] openid-connect.lua:163: phase_func(): failed to authenticate in openidc: request to the redirect_uri path but there's no session state found, client: 192.168.1.145, server: , request: "GET

we got this error, I think it is fine. because you did not set a correct redirect_uri.

when missing redirect_uri, it'll use ctx.var.request_uri as default value: http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_uri .

2020/10/10 06:47:45 [error] 25#25: *6045493 lua entry thread aborted: runtime error: /usr/local/apisix/apisix/plugins/echo.lua:96: attempt to index local 'conf' (a userdata value)
stack traceback:                                                                                                                                            
coroutine 0:                                                                                                                                             
        /usr/local/apisix/apisix/plugins/echo.lua: in function 'phase_fun'                                                                                     
        [string "route#41ee9eef-564e-4208-86e6-fc6834bd7178"]:17: in function 'phase_func'                                                                  
        /usr/local/apisix/apisix/script.lua:52: in function 'run'                                                                                                 
        /usr/local/apisix/apisix/init.lua:508: in function 'http_access_phase'  

@liuxiran that is another error message of plugin echo, but I do not find you enabled this plugin. so I think this error message is not related to this issue.

membphis avatar Oct 22 '20 04:10 membphis

2020/10/10 06:47:45 [error] 26#26: *6045490 [lua] openid-connect.lua:163: phase_func(): failed to authenticate in openidc: request to the redirect_uri path but there's no session state found, client: 192.168.1.145, server: , request: "GET

we got this error, I think it is fine. because you did not set a correct redirect_uri.

when missing redirect_uri, it'll use ctx.var.request_uri as default value: http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_uri .

2020/10/10 06:47:45 [error] 25#25: *6045493 lua entry thread aborted: runtime error: /usr/local/apisix/apisix/plugins/echo.lua:96: attempt to index local 'conf' (a userdata value)
stack traceback:                                                                                                                                            
coroutine 0:                                                                                                                                             
        /usr/local/apisix/apisix/plugins/echo.lua: in function 'phase_fun'                                                                                     
        [string "route#41ee9eef-564e-4208-86e6-fc6834bd7178"]:17: in function 'phase_func'                                                                  
        /usr/local/apisix/apisix/script.lua:52: in function 'run'                                                                                                 
        /usr/local/apisix/apisix/init.lua:508: in function 'http_access_phase'  

@liuxiran that is another error message of plugin echo, but I do not find you enabled this plugin. so I think this error message is not related to this issue.

@membphis Thank you very much~! since It has nothing wrong about the openid-connect schema, I'll try again to config a right redirect_uri :)

then close this issue, thx again~!

liuxiran avatar Oct 22 '20 07:10 liuxiran

I had the same problem. https://github.com/zmartzone/lua-resty-openidc/blob/v1.7.2/lib/resty/openidc.lua Line 1361 local session, session_error = r_session.start(session_opts) https://github.com/bungle/lua-resty-session/blob/v2.24/lib/resty/session.lua Line 320 return self, present session_error receives the value of present,session is not initialized present

tangjun2012 avatar Jan 05 '21 10:01 tangjun2012

I had the same problem. https://github.com/zmartzone/lua-resty-openidc/blob/v1.7.2/lib/resty/openidc.lua Line 1361 local session, session_error = r_session.start(session_opts) https://github.com/bungle/lua-resty-session/blob/v2.24/lib/resty/session.lua Line 320 return self, present session_error receives the value of present,session is not initialized present

I got the same error, how did you solve it finally?

lemonrains avatar Nov 25 '21 03:11 lemonrains

Refer the following link, I solved my problem.

https://stackoverflow.com/questions/49338403/openidc-with-keycloak-error-uthenticate-request-to-the-redirect-uri-path-but

Your redirect URI must not be set to "/" but to some arbitrary path that is not supposed to return content (like /redirect_uri). It is a "vanity" URL that is handled by lua-resty-openidc

lemonrains avatar Nov 25 '21 03:11 lemonrains

@lemonrains do we need to update the code or docs of APISIX?

membphis avatar Nov 27 '21 08:11 membphis

Came across the same problem today and did some testing on the problem with an up-to-date apisix instance. It seems like this problem (request to the redirect_uri path but there's no session state found) only happens if the user requested URI and the redirect_uri are identical.

The reason could be that the openid-connect plugin probably checks if the user requested URI is identical to redirect_uri and if that is the case assumes that user has already been redirected back from the Auth server and should already have a valid session cookie. The plugin hence expects a session cookie and then fails with the error above if it finds no session state. @membphis or @moonming could you maybe confirm that this is what the plugin does?

If my hypothesis is correct then I would assume this is a bug and I find that the approach of @lemonrains is not a good solutions. Here is why:

  • Assume you try to protect an upstream API with OpenID, say https://httpbin.org/image/png
  • The exposed route for the upstream could be https://example.com/image/png
  • If users without a session yet try to access https://example.com/image/png they should be redirected to the Auth server to redeem a session. (This redirect currently fails).
  • After the authentication passed the users should be redirected back to the original target URI (https://example.com/image/png) because that is the resource they initially tried to access. (Please note that this what the openid-connect plugin actually tries to do by default as redirect_uri has a default value of "ngx.var.request_uri", which is IMHO the right thing to do and absolutely correct. The docs are correct too, just the implementation in the plugin seems to have a bug ;) )

david-woelfle avatar Apr 06 '22 19:04 david-woelfle

@david-woelfle thanks for your detailed report 👍 @starsz @membphis please take a look, thx

moonming avatar Apr 06 '22 23:04 moonming

@starsz I have reopened this issue right now.

Do you have time to check this bug?

membphis avatar Apr 07 '22 01:04 membphis

@starsz I have reopened this issue right now.

Do you have time to check this bug?

Sure. Let me have a check.

starsz avatar Apr 07 '22 01:04 starsz

The reason could be that the openid-connect plugin probably checks if the user requested URI is identical to redirect_uri and if that is the case assumes that user has already been redirected back from the Auth server and should already have a valid session cookie. The plugin hence expects a session cookie and then fails with the error above if it finds no session state. @membphis or @moonming could you maybe confirm that this is what the plugin does?

Hi @david-woelfle .Yes, that's true. Now, Apache APISIX uses "lua-resty-openidc" to deal with the openid-connect loginc. You can refer to the code here :

https://github.com/zmartzone/lua-resty-openidc/blob/a468d13283d62ef5e3d14f02404294f7777c053d/lib/resty/openidc.lua#L1472-L1481

Assume you try to protect an upstream API with OpenID, say https://httpbin.org/image/png The exposed route for the upstream could be https://example.com/image/png If users without a session yet try to access https://example.com/image/png they should be redirected to the Auth server to redeem a session. (This redirect currently fails). After the authentication passed the users should be redirected back to the original target URI (https://example.com/image/png) because that is the resource they initially tried to access. (Please note that this what the openid-connect plugin actually tries to do by default as redirect_uri has a default value of "ngx.var.request_uri", which is IMHO the right thing to do and absolutely correct. The docs are correct too, just the implementation in the plugin seems to have a bug ;) )

Here, I think you may misunderstand the usage of redirect_uri. In fact:

  • Assume you try to protect an upstream API with OpenID, say https://httpbin.org/image/png
  • The exposed route for the upstream could be https://example.com/image/png
  • If users without a session yet try to access https://example.com/image/png they should be redirected to the Auth server to redeem a session and Apache APISIX will store the target_url (default is request URI) in session. You can refer : https://github.com/zmartzone/lua-resty-openidc/blob/a468d13283d62ef5e3d14f02404294f7777c053d/lib/resty/openidc.lua#L366-L371
  • After the authentication passed, the Auth server will redirect to the redirect_uri (which is config in Apache APISIX), and Apache APISIX will get the code and state from the redirection. You can refer: https://github.com/zmartzone/lua-resty-openidc/blob/a468d13283d62ef5e3d14f02404294f7777c053d/lib/resty/openidc.lua#L1092-L1204
  • And Apache APISIX will use the code and state to get the access_token, and use access_token to get the user info.
  • After this, Apache APISIX then will redirect to the target URI (which is stored in the session, is https://example.com/image/png).You can refer: https://github.com/zmartzone/lua-resty-openidc/blob/master/lib/resty/openidc.lua#L1205

So the flow should be like this:

image

In a conclusion, it's a bug.But I think it's a little bit hard to fix it.

Refer the following link, I solved my problem. https://stackoverflow.com/questions/49338403/openidc-with-keycloak-error-uthenticate-request-to-the-redirect-uri-path-but Your redirect URI must not be set to "/" but to some arbitrary path that is not supposed to return content (like /redirect_uri). It is a "vanity" URL that is handled by lua-resty-openidc

It's a quick way to fix it.

starsz avatar Apr 07 '22 02:04 starsz

I think we can improve the error log and status code at least. So I create an issue: https://github.com/apache/apisix/issues/6803

starsz avatar Apr 07 '22 10:04 starsz

Thank you for the detailed insights @starsz and for the super fast reply to @membphis and @moonming!

Hi @david-woelfle .Yes, that's true. Now, Apache APISIX uses "lua-resty-openidc" to deal with the openid-connect loginc. You can refer to the code here :

https://github.com/zmartzone/lua-resty-openidc/blob/a468d13283d62ef5e3d14f02404294f7777c053d/lib/resty/openidc.lua#L1472-L1481

I see the problem. I think from a generic OAuth point of view (like the Grafana example above) that code even makes sense.

So the flow should be like this:

Thanks once more, the graph and the explanation above is really useful for me. But there is one thing which I do not understand, maybe you can help me out with, it's about this step:

After the authentication passed, the Auth server will redirect to the redirect_uri (which is config in Apache APISIX), and Apache APISIX will get the code and state from the redirection. You can refer: https://github.com/zmartzone/lua-resty-openidc/blob/a468d13283d62ef5e3d14f02404294f7777c053d/lib/resty/openidc.lua#L1092-L1204

Seems like the redirect_uri (aka the proxiex-token-url in your sequence diagram) is an internal endpoint that APISIX needs to finish the the auth process, that is, to trigger the exchange code for an access token, right? It doesn't even depend on the upstream/resource server at all as those are not involved in the information exchange. Neither is the user btw. and the user agents just follows redirects. Now the question: Why should the admin of an APISIX gateway decide about the redirect_uri at all? Couldn't APISIX provide some generic auth callback endpoint that is automatically send to the auth server? I mean like e.g. Grafana that provides a hardcoded endpoint (https://your-grafana-server/login/generic_oauth -> see docs here).

david-woelfle avatar Apr 07 '22 19:04 david-woelfle

Why should the admin of an APISIX gateway decide about the redirect_uri at all

Yes, the best way is that the admin doesn't need to care about the redirect_uri. It's a point that can be improved.

Couldn't APISIX provide some generic auth callback endpoint that is automatically sent to the auth server

Thanks @david-woelfle.It's a good idea. But there is some difference from Grafana. Apache APISIX is a gateway, we don't want to expose a fixed URL in the gateway since it will influence other APIs. So we should do more research to provide the best solution.

starsz avatar Apr 08 '22 01:04 starsz

Hello guys i would like some help to understand why im getting this error, i implemented OIDC flow as above, the problem is that after authentication some times i complete the flow and apisix just return me to auth endpoint and in other times i get this error. OIDC authentication failed: request to the redirect_uri path but there's no session state found Can some 1 light me?. Thanks in advance.

Xarxavier avatar Apr 08 '22 08:04 Xarxavier

2020/10/10 06:47:45 [error] 26#26: *6045490 [lua] openid-connect.lua:163: phase_func(): failed to authenticate in openidc: request to the redirect_uri path but there's no session state found, client: 192.168.1.145, server: , request: "GET

we got this error, I think it is fine. because you did not set a correct redirect_uri.

when missing redirect_uri, it'll use ctx.var.request_uri as default value: http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_uri .

2020/10/10 06:47:45 [error] 25#25: *6045493 lua entry thread aborted: runtime error: /usr/local/apisix/apisix/plugins/echo.lua:96: attempt to index local 'conf' (a userdata value)
stack traceback:                                                                                                                                            
coroutine 0:                                                                                                                                             
        /usr/local/apisix/apisix/plugins/echo.lua: in function 'phase_fun'                                                                                     
        [string "route#41ee9eef-564e-4208-86e6-fc6834bd7178"]:17: in function 'phase_func'                                                                  
        /usr/local/apisix/apisix/script.lua:52: in function 'run'                                                                                                 
        /usr/local/apisix/apisix/init.lua:508: in function 'http_access_phase'  

@liuxiran that is another error message of plugin echo, but I do not find you enabled this plugin. so I think this error message is not related to this issue.

Hi, @Xarxavier I think your problem is the same as membphis. You can read the issue, and I think you will get the answer.

starsz avatar Apr 08 '22 09:04 starsz

2020/10/10 06:47:45 [error] 26#26: *6045490 [lua] openid-connect.lua:163: phase_func(): failed to authenticate in openidc: request to the redirect_uri path but there's no session state found, client: 192.168.1.145, server: , request: "GET

we got this error, I think it is fine. because you did not set a correct redirect_uri. when missing redirect_uri, it'll use ctx.var.request_uri as default value: http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_uri .

2020/10/10 06:47:45 [error] 25#25: *6045493 lua entry thread aborted: runtime error: /usr/local/apisix/apisix/plugins/echo.lua:96: attempt to index local 'conf' (a userdata value)
stack traceback:                                                                                                                                            
coroutine 0:                                                                                                                                             
        /usr/local/apisix/apisix/plugins/echo.lua: in function 'phase_fun'                                                                                     
        [string "route#41ee9eef-564e-4208-86e6-fc6834bd7178"]:17: in function 'phase_func'                                                                  
        /usr/local/apisix/apisix/script.lua:52: in function 'run'                                                                                                 
        /usr/local/apisix/apisix/init.lua:508: in function 'http_access_phase'  

@liuxiran that is another error message of plugin echo, but I do not find you enabled this plugin. so I think this error message is not related to this issue.

Hi, @Xarxavier I think your problem is the same as membphis. You can read the issue, and I think you will get the answer.

Hi @starsz I change the redirect_uri callback to "pathtoprotect"/callback and some times it just redirect to the Auth Server and others keep throwing 500 error (state not found), i cant figure out why, some toughts?

Xarxavier avatar Apr 08 '22 10:04 Xarxavier

Couldn't APISIX provide some generic auth callback endpoint that is automatically sent to the auth server

Thanks @david-woelfle.It's a good idea. But there is some difference from Grafana. Apache APISIX is a gateway, we don't want to expose a fixed URL in the gateway since it will influence other APIs. So we should do more research to provide the best solution.

I see your point @starsz. How about a configurable endpoint, like what is already implemented in the prometheus plugin? Could be a simple configuration option like this:

plugin_attr:
  openid-connect:
    redirect_uri: /apisix/redirect

And last but not least, thanks very much for working on this!

david-woelfle avatar Apr 08 '22 13:04 david-woelfle

2020/10/10 06:47:45 [error] 26#26: *6045490 [lua] openid-connect.lua:163: phase_func(): failed to authenticate in openidc: request to the redirect_uri path but there's no session state found, client: 192.168.1.145, server: , request: "GET

we got this error, I think it is fine. because you did not set a correct redirect_uri. when missing redirect_uri, it'll use ctx.var.request_uri as default value: http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_uri .

2020/10/10 06:47:45 [error] 25#25: *6045493 lua entry thread aborted: runtime error: /usr/local/apisix/apisix/plugins/echo.lua:96: attempt to index local 'conf' (a userdata value)
stack traceback:                                                                                                                                            
coroutine 0:                                                                                                                                             
        /usr/local/apisix/apisix/plugins/echo.lua: in function 'phase_fun'                                                                                     
        [string "route#41ee9eef-564e-4208-86e6-fc6834bd7178"]:17: in function 'phase_func'                                                                  
        /usr/local/apisix/apisix/script.lua:52: in function 'run'                                                                                                 
        /usr/local/apisix/apisix/init.lua:508: in function 'http_access_phase'  

@liuxiran that is another error message of plugin echo, but I do not find you enabled this plugin. so I think this error message is not related to this issue.

Hi, @Xarxavier I think your problem is the same as membphis. You can read the issue, and I think you will get the answer.

Hi @starsz I change the redirect_uri callback to "pathtoprotect"/callback and some times it just redirect to the Auth Server and others keep throwing 500 error (state not found), i cant figure out why, some thoughts?

Looks strange. Can you provide your config of the openid-connect plugin. And the URI that returns 500?

starsz avatar Apr 10 '22 06:04 starsz

Couldn't APISIX provide some generic auth callback endpoint that is automatically sent to the auth server

Thanks @david-woelfle.It's a good idea. But there is some difference from Grafana. Apache APISIX is a gateway, we don't want to expose a fixed URL in the gateway since it will influence other APIs. So we should do more research to provide the best solution.

I see your point @starsz. How about a configurable endpoint, like what is already implemented in the prometheus plugin? Could be a simple configuration option like this:

plugin_attr:
  openid-connect:
    redirect_uri: /apisix/redirect

And last but not least, thanks very much for working on this!

I think it's a good idea. And I will try to have a test of it.

starsz avatar Apr 10 '22 06:04 starsz

Should redirect_uri be configured as a plugin configuration instead of plugin attributes? Different OIDC clients may need different redirect uri.

spacewander avatar Apr 10 '22 12:04 spacewander