I am using Nginx as an authenticating reverse proxy using OpenResty & Keycloak within AWS Kubernetes. Both Nginx and Keycloak are pods with a load balancer looking after the https.
The problem I am facing is that Nginx needs to send a request to Keycloak to perform a logout. In order to do this, the following sequence of events is followed:
- User clicks “logout” on our UI (or types the url manually)
- Request is sent to “https://external.xxx/logout”
- This is interpreted by Nginx as a request to logout and so it performs the following:
Discovery request is sent to “http://internal.xxx/auth/realms/xxx/.well-known/openid-configuration”
The endpoint is read from this response: "end_session_endpoint":"https://external.xxx/auth/realms/xxx/protocol/openid-connect/logout”
A request is then sent to this endpoint from Nginx to initiate the logoff.
- The user is logged off & returned to login screen.
I believe that the issue is that the endpoint is returned as https://external.xxx as opposed to http://internal.xxx and I can find no way to change this in keycloak. Consequently the nginx pod is now making a request to the public external url/ip and this needs to be allowed in the egress policy. Adding the external IP address to the egress rule does cause it to work - but is obviously a bit disgusting.
Here's the relevant part of the nginx config:
# Secured - Auth through keycloak
access_by_lua '
-- Require authentication for everything except keycloak
if (ngx.var.request_uri:find("^/auth/" ) == nil) then
local opts = {
redirect_uri_path = "/redirect_uri",
discovery = "http://keycloak.xxx.svc.cluster.local/auth/realms/xxx/.well-known/openid-configuration",
client_id = "nginx",
client_secret = "xxx",
redirect_uri_scheme = "http",
logout_path = "/logout",
post_logout_redirect_uri = "http://192.168.1.12/grafana/logout",
revoke_tokens_on_logout = true
}
-- 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
end
';
My questions are:
- I'm 'assuming' that the end_session_endpoint is what is being used here - is this assumption correct?
- Is there a way to override the end_session_endpoint returned by Keycloak. I can see that several other endpoints return the internal host when queried using the internal host - (and external when external) but the end_session_endpoint is always the external.
Any insight here is greatly appreciated!!