I have an nginx/openresty client to a keycloak server for authorization using openid. I am using lua-resty-openidc to allow access to services behind the proxy.
The user can access his profile at
https://<my-server>/auth/realms/<real-name>/account
and logout through
https://<my-server>/auth/realms/<real-name>/protocol/openid-connect/logout
The problem is that, even after logout, the user can still access the services behind the server, basically it seems the token he gets from keycloak is still valid or something.... This is also a behaviour that has been observed by other users, see for example this question on how to logout from keycloak the comments from ch271828n
How can I ensure that after logout the user will no longer be able to get access until he logs in anew?
I had to check the lua source code, but I think I have figured the logout behaviour out: Lua-resty-openidc establishes sessions, and they are terminated when a specific url access is detected (it is controlled by opts.logout_path
which we will need to be set to an address in the path of service, e.g. .../service/logout)
In essence, there are two urls that need to be hit, one for keycloak logout, and one for openresty session logout. Accessing the keycloak logout url https://<keycloak-server>/auth/realms/<my-realm>/protocol/openid-connect/logout
is done by lua after we access the opts.logout_path at https://<our-nginx-server>/service/logout
So after setting up everything correctly, all we have to do to logout is hit https://<our-nginx-server>/service/logout
. This will destroy the session and log us out.
I think we need to set opts.revoke_tokens_on_logout
to true
, Also note that from my experiments, for some reason, setting up a redirect_after_logout_uri
may result in the user not signing out due to redirections.
In order to redirect to e.g. foo.bar after logout we can do the ?redirect_uri=https://foo.bar/
part. We can also redirect back to our service page, in which case it will ask for authentication anew...
Here is an example of what we need to have for nginx.conf to make this work....
location /myservice/ {
access_by_lua_block {
local opts = {
redirect_uri_path = "/myservice/auth",
discovery = "https://<keycloak-server>/auth/realms/<my-realm>/.well-known/openid-configuration",
client_id = "<my-client-id>",
client_secret = "<the-clients-secret>",
logout_path = "/service/logout",
revoke_tokens_on_logout = true,
redirect_after_logout_uri = "https://<keycloak-server>/auth/realms/<my-realm>/protocol/openid-connect/logout?redirect_uri=https://foo.bar/",
session_contents = {id_token=true} -- this is essential for safari!
}
-- call introspect for OAuth 2.0 Bearer Access Token validation
local res, err = require("resty.openidc").authenticate(opts)
if err then
ngx.status = 403
ngx.say(err)
ngx.exit(ngx.HTTP_FORBIDDEN)
end
}
# I disbled caching so the browser won't cache the site.
expires 0;
add_header Cache-Control private;
proxy_pass http://my-service-server.cloud:port/some/path/;
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";
}