zmartzone / lua-resty-openidc

OpenID Connect Relying Party and OAuth 2.0 Resource Server implementation in Lua for NGINX / OpenResty
Apache License 2.0
968 stars 247 forks source link

rotating refresh tokens #524

Closed ronnybremer closed 2 months ago

ronnybremer commented 2 months ago

When your token expires lua-resty-openidc will try o obtain a new one using the refresh token it has obtained when the initial flow completed.

Originally posted by @bodewig in https://github.com/zmartzone/lua-resty-openidc/issues/452#issuecomment-1257182462

This seems to indicate, that lua-resty-openidc does not support rotating refresh tokens (a new refresh token is returned when refreshing a token with it, and needs to be used for the next refresh). Is that true?

ronnybremer commented 2 months ago

I verified the code and it is taking a newly returned refresh token into account (stores it into the session, so it's used at the next refresh token call). However, the culprit might lie a few lines later:

https://github.com/zmartzone/lua-resty-openidc/blob/9f3a4fcade930f6f38ee0cb43cabf50cebffbcc9/lib/resty/openidc.lua#L1417-L1419

After successfully using the refresh token to get a new access token (an in my case refresh token) it does generate a new session ID, invalidating the previous session. Why is this necessary? Couldn't the new tokens being stored at the session object and used with the same session ID?

bodewig commented 2 months ago

see https://github.com/zmartzone/lua-resty-openidc/issues/190 for an explanation why we are creating a new session here.

Oh, I talked about "the initial flow" in #452 because it was the first refresh. Of course lua-resty-openidc not only replaces the access token on refresh but all tokens it receives (there may be a new id token or not, there should be a new refresh token).

ronnybremer commented 2 months ago

Thank you @bodewig for the pointer, I understand the reasoning now.

In fact, I am trying comprehend the logic behind an issue I see in APISIX's OIDC plugin, which uses openidc-resty. When the IDP returns a refresh token, it sometimes gets used to get a new access token, other times not. Also I never see a second attempt to refresh a token, it just redirects to the authentication workflow. And for API access (which doesn't support redirects), it somehow doesn't end up using the local function openidc_access_token, so the access token never gets refreshed and a DENIED is returned.

I will close this issue now, as the code in here seems to do what it is supposed to do and I will further dive into APISIX.