Due to some updates in our infrastructure, I was looking for a means to authenticate nginx against a keycloak backend. I found some solutions, using Lua or commercial plugins.
I thought, that this might be doable with „pure nginx means“ only, and I think, to some degree, I succeeded.
Lets just skip the explanation, and show some code, where we want to protect location „/“ by basic auth forwarded to keycloak
# nginx.conf
location / {
root /var/html;
satisfy any;
auth_request /auth_keycloak;
}
location /auth_keycloak {
proxy_pass https://keycloak.com/realms
/myRealm/protocol/openid-connect
/token;
proxy_method POST;
proxy_pass_header Authorization;
proxy_set_header Content-Type
"application/x-www-form-urlencoded";
proxy_set_body "client_id=clientId&
client_secret=clientSecret&
grant_type=password";
}
We delegate the authentication in „/“ to the location „/auth_keycloak“ and as mentioned in the documentation: If the subrequest returns a 2xx response code, the access is allowed. If it returns 401 or 403, the access is denied with the corresponding error code.
So we need to fix a client in keycloak, that will answer correctly to the given request. Formally the passed request is a „direct access grant“ request. But there is a slight change. No username and password are passed, instead these are passed via proxy_pass_header Authorization.
How can this be achieved? The secret is in the supported flows. I assume that you are familiar with keycloak basics, thus I only show the relevant parts:
I override the Direct Grant Flow with a http challenge flow, which removes the requirement for the username and password passing as form value, and reads the Authorization header.
Also I deactive the other non-required capabilities!
Now, at least for me, with this reduced solution, I managed to do Nginx Basic Authentication backed by a keycloak service.