lua-resty-openidc
lua-resty-openidc copied to clipboard
Problem with integration with keycloak
Environment
- lua-resty-openidc version (e.g. 1.7.6)
- Keycloak 23.0.7
- OpenResty 1.25.3.1
Expected behaviour
I have the following openresty configuration:
##I added these dictionaries based on recommendations from previous threads on this issue lua_shared_dict discovery 1m; lua_shared_dict jwks 1m; lua_shared_dict introspection 10m; lua_shared_dict sessions 10m;
##For correct operation of ssl lua_ssl_verify_depth 5; lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.pem;
server { listen 443 ssl;
ssl_certificate /etc/ssl/certs/domain.crt; ssl_certificate_key /etc/ssl/private/domain.key;
access_log /home/portal/logs/log.log; error_log /home/portal/logs/log_error.log info;
resolver 8.8.8.8;
fastcgi_read_timeout 600; client_header_timeout 30; ##I added these session secret based on recommendations from previous threads on this issue set $session_secret 1234567890;
location / { access_by_lua_block { local opts = { redirect_uri = "https://domain.com/callback", discovery = "https://sso.domain.com/realms/ditust/.well-known/openid-configuration", client_id = "test_app", client_secret = "123123123132132132132132131323211", ssl_verify = "no", }
-- call authenticate for OpenID Connect user authentication
local res, err,target, session = require("resty.openidc").authenticate(opts)
session:close()
if err then
ngx.status = 403
ngx.say(err)
ngx.exit(ngx.HTTP_FORBIDDEN)
end
ngx.req.set_header("X-USER", res.id_token.sub)
}
proxy_pass https://test.domain.com/
} }
Steps to reproduce:
- go to site https://domain.com/;
- redirects me to KC;
- successful authentication;
- redirects back to https://domain.com/callback with authentication headers;
- got an error request to the redirect_uri path but there's no session state found.
More details: When I go to my site https://domain.com/ I get a redirect to keycloak. After successful authentication, I receive a reverse redirect to my site with all the headers necessary for authentication, but it returns a 403 error. This is due to the fact that the authenticate(opts) method could not return res and lua will throw a 403 error.
After my research, I found out that the problem is that openresty does not remember the session. the session.create() method, when used again, does not restore the previous session, but creates a new one. This can also be observed from the error in the logs:
openidc.lua:1511: authenticate(): request to the redirect_uri path but there's no session state found
After researching a lot of articles, I think that this configuration should work correctly in this form
If you have any ideas or suggestions on how to help, I would be grateful
thank you in advance!
I have exactly the same error after i updated my Windows to Windows 11 Version 23H2. Before all worked perfectly.
request to the redirect_uri path but there's no session state found
almost always means your browser did not send the session cookie lua-resty-session expects to be present. This can happen for a number of reasons and your browser's developer tools may help.
The most common case is the Cookie's SameSite
setting being too strict for your OIDC setup - for example if you use the "form_post" response_mode then SameSite
must be set to None
as even Lax
would be too strict. For the "normal" redirect based response mode SameSite=Lax
should work. SameSite=Strict
will not work with any OIDC login flow at all. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value for the attribute. See https://github.com/bungle/lua-resty-session/tree/v3.10?tab=readme-ov-file#string-sessioncookiesamesite for the way to configure the session cookie's SameSite value.
Still not working. This is my Configuration:
` worker_processes 1;
events { worker_connections 128; }
http { lua_package_path '~/lua/?.lua;;'; resolver 127.0.0.11 ipv6=off; lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; lua_ssl_verify_depth 5; lua_shared_dict discovery 1m; lua_shared_dict jwks 1m;
server { server_name localhost; listen 0.0.0.0:80; listen [::]:80;
location /auth {
proxy_pass https://<realm>/;
proxy_set_header Host $http_host;
proxy_pass_request_headers on;
}
location / {
set $session_cookie_samesite off;
access_by_lua_block {
local opts = {
redirect_uri_path = "/redirect_uri",
discovery = "https://<domain>/realms/<realm>/.well-known/openid-configuration",
client_id = "<client_id",
client_secret = "<secret>",
scope = "openid email",
access_token_expires_leeway = 30,
accept_none_alg = false,
accept_unsupported_alg = false,
renew_access_token_on_expiry = true,
logout_path = "/logout",
redirect_after_logout_uri = "https://<domain>/realms/<realm>/protocol/openid-connect/logout",
redirect_after_logout_with_id_token_hint = false,
session_contents = {access_token=true}
}
local res, err, target, session = require("resty.openidc").authenticate(opts)
session:close()
if err then
ngx.status = 403
ngx.say(err)
ngx.exit(ngx.HTTP_FORBIDDEN)
end
ngx.req.set_header("Authorization", "Bearer " .. res.access_token)
ngx.req.set_header("X-User", res.id_token.sub)
ngx.header['Authorization'] = "Bearer " .. res.access_token
}
proxy_pass http://host.docker.internal:8000/;
expires 0;
add_header Cache-Control private;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
} } `
The strange thing is that it worked until yesterday, before i made the update of Widnows 11
off
is not going to help you at all, it means "don't set the SameSite value at all when setting the Cookie" which leaves you at the default of your browser - which is Lax
for all modern browsers.
Most likely your Windows update has given you a different Browser with changed (default) settings.
The most reliable source for debugging the problem are the developer tools of your browser. Does you browser see the Cooke when lua-resty-openidc redirects your browser to your OIDC provider? Does it reject it for any reason? Does it send it back when returning? If not, does it tell you why not?
If it does send back the Cookie, then SameSite is not the issue and the problem is a different one.
Sending screenshots is not going to help, I'm afraid. You need to look at the individual requests (the last two in your screenshot) in your dev tools and see whether the cookies are present and if it is not present in the second to see why it is not included.This may or may not get logged to your browser's console. Please understand I'm trying to help you to help yourself here as the problem is with your setup.
In order to rule out SameSite, you should set the value to None and verify this is what the Set-Cookie header says when redirecting to Keycloak. You may also want to check whether any kind of 3rd party cookie policy is present that would reject 3rd party cookies regardless of SameSite=None.
I think it is a problem of keycloak
Could there be a problem on the keyCloak server side? maybe there is a parameter that prevents cookies from being returned?
This is not how Cookies work. Keycloak has no way to influence the cookies your browser sends to your relying party server.
Where is then the place to search for this problem?
I decided to try authentication through different combinations of browsers and systems.
Everywhere there are problems that cookies are not saved in the browser.
I have same issue with another idp provider. I have added some logs in codes and I saw that cookies work fine. but still I get this error.
You might have done what I just spent 5 hours troubleshooting..
lua-resty-session needs to be fixed at version 3.10 or lower. If you've pulled the latest by defult, these kinds of errors will pop up
@lexiconzero Are you saying that you were able to get a working state of the system by running it on a version lower than 3.10?
That's right - pinning lua-resty-session to version 3.10 corrected this issue
@lexiconzero It didn't work for me( I have the following error in the logs
lua entry thread aborted: runtime error: /usr/local/openresty/lualib/resty/openidc.lua:965: bad argument #1 to 'match' (string expected, got nil)
Here's my code for the location I'm using in openresty. Ive also set a session secret above in the server block.
location / {
access_by_lua_block {
local opts = {
redirect_uri = "/redirect_uri",
accept_none_alg = false,
renew_access_token_on_expiry = true,
discovery = "http://keycloak:8080/realms/test/.well-known/openid-configuration",
client_id = "nginx",
client_secret = "xxx",
logout_path = "/logout",
redirect_after_logout_with_id_token_hint = true,
redirect_uri_scheme = "https",
accept_unsupported_alg = false,
renew_access_token_on_expiry = true,
revoke_tokens_on_logout = true,
ssl_verify = "no",
session_contents = {id_token=true}
}
local oidc = require("resty.openidc")
oidc.set_logging(nil, { DEBUG = ngx.INFO })
local res, err = oidc.authenticate(opts)
if err then
ngx.status = 403
ngx.exit(ngx.HTTP_FORBIDDEN)
end
}
proxy_set_header Host host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass_request_headers on;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_pass http://ipaddress:8123;
}
Here's how I load this into the podman container it runs in via a compose file
openresty:
hostname: hostname
restart: unless-stopped
image: docker.io/bitnami/openresty:latest
volumes:
- /home/user/openrestyconf/openresty-homeassist.conf:/opt/bitnami/openresty/nginx/conf/server_blocks/openresty-homeassist.conf:Z
- /home/user/openrestyconf/openresty-keycloak.conf:/opt/bitnami/openresty/nginx/conf/server_blocks/openresty-keycloak.conf:Z
- /home/user/openrestyconf/lua-opm-files.sh:/docker-entrypoint-initdb.d/lua-opm-files.sh:Z
ports:
- 3002:3002
- 3003:3003
depends_on:
- keycloak_postgress
- keycloak
And the entrypoint file
#Lua-opm-files.sh
#!/bin/bash
opm install ledgetech/lua-resty-http
opm install bungle/lua-resty-session=3.10
opm install cdbattags/lua-resty-jwt
opm install zmartzone/lua-resty-openidc
Any news about that ?
What is the issue and how can I help to resolve this ?