keycloak and guacamole configuration behind httpd reverse proxy configuration - keycloak

I have Apache httpd configured as a reverse proxy with SSL. I'm trying to configure keycloak and guacamole using http behind the proxy. I'm using the keycloak, mysql, guacd and guacamole containers. I have the entire flow working until keycloak attempts to redirect back to the guacamole page. FYI...my configuration is very similar to the following question, but with a different access error shown below: How to configure Keycloak to work with Guacamole's OpenID plugin?
So, user hits webserver via: https://example.com/guacamole/. Httpd redirects to http://guacamole:8080/guacamole. Guacamole redirects to keycloak for authentication. Login as valid user and the redirect to guacamole fails.
My guacamole is configured as:
openid-jwks-endpoint: https://example.com/auth/realms/Guacamole-test/protocol/openid-connect/certs
openid-issuer: https://example.com/auth/realms/Guacamole-test
openid-client-id: Guacamole
openid-redirect-uri: https://example.com/guacamole/
My httpd configuration:
ServerName example.com
SSLEngine On
SSLCertificateFile /opt/test.crt
SSLCertificateKeyFile /opt/test.key
ProxyPass /guacamole/ http://guacamole:8080/guacamole/ flushpackets=on
ProxyPassReverse /guacamole/ http://guacamole:8080/guacamole/
ProxyPass /guacamole/websocket-tunnel ws://guacamole:8080/guacamole/websocket-tunnel
ProxyPassReverse /guacamole/websocket-tunnel ws://guacamole:8080/guacamole/websocket-tunnel
ProxyPass /auth/ http://keycloak:8080/auth/
ProxyPassReverse /auth/ http://keycloak:8080/auth/
</VirtualHost>
I'm getting following error in guacamole:
INFO o.a.g.a.o.t.TokenValidationService - Rejected invalid OpenID token: Unable to process JOSE object (cause: org.jose4j.lang.UnresolvableKeyException: Unable to find a suitable verification key for JWS w/ header {"alg":"RS256","typ" : "JWT","kid" : "bSv9K9W2us7SaUamJP3bWD1HWJuo6hbne2t3Gsc6V44"} due to an unexpected exception (javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target) while obtaining or using keys from JWKS endpoint at https://example.com/auth/realms/ocprealm/protocol/openid-connect/certs): JsonWebSignature{"alg":"RS256","typ" : "JWT","kid" : "bSv9K9W2us7SaUamJP3bWD1HWJuo6hbne2t3Gsc6V44"}->eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJiU3Y5SzlXMnVzN1NhVWFtSlAzYldEMUhXSnVvNmhibmUydDNHc2M2VjQ0In0.eyJleHAiOjE2MDc5MDE3NDAsImlhdCI6MTYwNzkwMDg0MCwiYXV0aF90aW1lIjoxNjA3OTAwODI1LCJqdGkiOiJhYmI1MDY5Zi01MTYzLTQ2ZjUtODA2ZC05M2ZkODU2YmQxMzciLCJpc3MiOiJodHRwczovL3Vzd2Rzcy5wcm9nZW55Lm5ldC9hdXRoL3JlYWxtcy9vY3ByZWFsbSIsImF1ZCI6Ikd1YWNhbW9sZSIsInN1YiI6IjE4MDRjOWJiLTZiOTEtNDY0YS04N2I1LWQ4MDNiY2Y3YWZmNCIsInR5cCI6IklEIiwiYXpwIjoiR3VhY2Ftb2xlIiwibm9uY2UiOiJoazc5NmlmZHUwdmdvcjJxcnZidDNqZmowcCIsInNlc3Npb25fc3RhdGUiOiJiZWNjZTZmOS01MDQ2LTQzMWEtOTQzNy1hMDczYTRhNDZhNGIiLCJhY3IiOiIwIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiR3V5IFNoZXBoZXJkIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiZ3NoZXBoZXJkIiwiZ2l2ZW5fbmFtZSI6Ikd1eSIsImZhbWlseV9uYW1lIjoiU2hlcGhlcmQiLCJlbWFpbCI6ImdzaGVwaGVyZEBwcm9nZW55Lm5ldCJ9.Fm2Vfep4N611KwSJc6MvhH80C3wca_T2If1YSVhzZdeC2eVh-v0_OCnEshcl_huta4a2VqolraqmqMDaxalAdnHO4jes71a2ndDfwoCnp1B06EBPL8kNnQeIHNM3fYps2GuhBqWLmfDDSIvXPlcnctrPKop8PQDglHSsiJOGgWgzfrQbG1zFlw0jupJVaYGY6P8q3Lji5ryIcStNATcuf1dCvF_v1oqoacYsRNFljyg7Xf0ZQIuA53xY3czKkiVVqZt55LArjAv1cPmrekkf77NlGpFzPbyw29_yItAy1rPqxfYphYDCm55qM97agjIE7WsKKC5lHwZ6gCWoMIcrMw
I don't understand why it is attempting to use SSL validation on the final redirect. I believe after keycloak validates the login and attempts to redirect back to https://example.com/guacamole/ the httpd configuration should proxy this to http://guacamole:8080/guacamole. I've also tried configuring keycloak with the tls.key and tls.crt according to the keycloak documentation to see if it made any difference but it does not.
Any help would be greatly appreciated as I am obviously missing or not understanding something in the configuration.

You are using OIDC, so when Guacamole receives the JWT key it is trying to validate the signature of the token. To do that, it has to contact Keycloak (via https) to retrieve the public key used to sign the token. This is failing with a SSL handshake error. Probably the JVM for Guacamole does not trust the SSL cert so you need to import it to the JVM keystore.
I do not think it is related to your problem, but when running Keycloak like this behind a proxy there are some attributes you need to set. I run Keycloak in Docker and you do it with environment variables. These two are fairly critical to set:
KEYCLOAK_FRONTEND_URL="https://hostname/auth/"
PROXY_ADDRESS_FORWARDING="true"
If you are not using the Docker version you can pretty easily translate how these values are communicated to Keycloak when it starts here: https://github.com/keycloak/keycloak-containers/blob/11.0.3/server/tools/docker-entrypoint.sh

Related

No Login Page shown with Keycloak and Quarkus

I have a keycloak Server running on my localhost with port 8081.
I'm trying to connect my Quarkus application with it to secure REST-Endpoints.
However I'm not able to Login to my Keycloak server.
I annotated an /test endpoint with #RolesAllowed("user"). Since then I can't access the endpoint but I get an Empty page with a 401 Unauthorized error in the Web console.
What I want is that I get redirected to the Keycloak default page so I can authorize myself. Any ideas why that is not happening?
Here is my application.properties Keycloak configuration:
quarkus.oidc.auth-server-url=http://localhost:8081/realms/TestRealm
quarkus.oidc.client-id=testclient
quarkus.oidc.credentials.secret=MYSECRET
quarkus.oidc.tls.verification=none
quarkus.keycloak.policy-enforcer.enable=false
logging.level.org.keycloak=DEBUG
resteasy.role.based.security=true
quarkus.http.cors=true
quarkus.http.port=8080
when I set policy enforcer to true I can't access any endpoint.
TestRealm has a Resource configured with a /test endpoint.
In the Quarkus documentation for keycloak they said that you don't need to setup your own Keycloak Server in Dev mode since Quarkus comes with one. Might that be the Problem? is my Quarkus Application not connecting to my Keycloak server? And if so, how can I force quarkus in dev mode to use my Keycloak server?
EDIT: I figured out that I have access to my endpoint if I send the request with the Bearer token, so I guess Quarkus is accessing my Keycloak instance.
Still, why don't I get forwarded to the default Keycloak login page when trying to access my Rest endpoint via my browser? Am I missing any configuration?
For anyone with the same issue I fixed it by adding:
quarkus.oidc.auth-mechanism=keycloak
quarkus.oidc.application-type=web-app
quarkus.http.auth.permission.authenticated.paths=/*
quarkus.http.auth.permission.authenticated.policy=authenticated
To the config

KeyCloak - ingress does not allow connecting over https service

I have installed keycloak using helm.
A Traefik ingress is created to allow access from public
After the admin password is created from localhost:8080, i am able to login into admin console only when i am port forwarded and local access.
When i use the public url and click on admin console, it redirects to https://website/auth/admin/master/console/ and shows a blank page.
I found the problem but when i change the servicePort: https inside ingress, i get an internal server error
status code 500.
when i use http port,i get these errors:
Mixed Content: The page at 'https://url/auth/admin/master/console/' was loaded over HTTPS, but requested an insecure script 'http://url/auth/js/keycloak.js?version=mxda6'. This request has been blocked; the content must be served over HTTPS.
Mixed Content: The page at 'https://url.ca/auth/admin/master/console/' was loaded over HTTPS, but requested an insecure script 'http://url/auth/js/keycloak.js?version=mxda6'. This request has been blocked; the content must be served over HTTPS.
i looked through traefik logs:
level=debug msg="'500 Internal Server Error' caused by: x509: cannot validate certificate for x.x.x.x because it doesn't contain any IP SANs"
I found a fix but it still doesn't answer my question why when ingress points to https, it doesnt work. Is there an answer?
So the fix is to add this under ENV in the statefulset keycloak deployment.
In the ingress, the service port is http
- name: PROXY_ADDRESS_FORWARDING
value: "true"
i found it at https://github.com/eclipse/che/issues/9429
I had the same issue. The white screen isn't helpful, but the browser console is. It is blocking mixed content, namely the script http://url/auth/js/keycloak.js?version=mxda6.
The documentation on Docker Hub says:
Specify frontend base URL
To set a fixed base URL for frontend requests use the following environment value (this is highly recommended in production):
KEYCLOAK_FRONTEND_URL: Specify base URL for Keycloak (optional, default is retrieved from request)
I provided the external url with https scheme in my manifest and the script in question is now appearing in the index.html as https url.
- name: KEYCLOAK_FRONTEND_URL
value: "https://url/auth"
Since it is "highly recommended" I suppose there are more slight problems without this variable set, like other links being generated wrong, e.g. in emails though I didn't check that yet.

Keycloak Admin Console requires HTTPS when connected remotely (Should I disable SSL)

I am connecting to Keycloak remotely. And when I try to open the Admin Console, I get an error saying HTTPS required.
In one of the websites, it says that I should do this: "update REALM set ssl_required='NONE' where id = 'master';"
But I do not know the consequences of doing this. Will this make it unsecure? Or can I reverse this?
Thank you
(And If I would run Keycloak within a docker image would this problem be solved?)
Admim console uses open id connect protocol, which needs HTTPS to be secure. So it isn't good idea to disable ssl in the prod environment.
Keycloak in the container doesn't solve your problem. But it provides user friendly approach to generate selfsigned cert - Keycloak Docker HTTPS required
Secure option is to generate valid TLS certificate and use it in your Keycloak instance, so you have valid secure TLS/HTTPS connection.

keycloak/louketo gatekeeper -- doesn't automatically redirect to keycloak login

I am setting up gatekeeper/louketo as a reverse proxy for a browser app. I have the proxy deployed as a sidecar in a kubernetes pod, with keycloak elsewhere in the same cluster (but accessed by a public URL). Gatekeeper is behind an nginx ingress, which does tls termination.
[I have tried both the most current louketo version and also the fork oneconcern/keycloak-gatekeeper. Some differences, but the issue is the same, so I think its a problem in my configuration.]
Gatekeeper, no matter how I set up the config, reads the discovery url of my realm, but then doesn't redirect on login there. Rather it redirects to my upstream app, using the /oauth/authorize path. I can manually force my app to redirect again to keycloak, but on return from keycloak, gatekeeper doesn't recognize the cookie, and catches me in a redirect loop.
It would seem I am making some simple config error, but I've been working on this for two days, and am at my wit's ends. (Even hacked in extra debugging into the go code, but haven't studied it enough to really know what it is doing.)
My config (best guess of many different variants tried):
- --config=/var/secrets/auth-proxy-keycloak-config.yaml
- --discovery-url=https://auth.my-domain.com/auth/realms/my-realm
- --listen=:4000
- --upstream-url=http://127.0.0.1:3000
- --redirection-url=https://dev.my-domain.com/
- --enable-refresh-tokens=true
- --enable-default-deny=true
- --resources=uri=/*|roles=developer
- --resources=uri=/about|white-listed=true
- --resources=uri=/oauth/*|white-listed=true
The ingress serves https://dev.my-domain.com and routes to port 4000, which is the auth proxy sidecar. It is setup with a lets-encrypt certificate, and terminates tls. I don't use tls in the proxy (should I?). Upstream app at port 3000. Keycloak is at auth.my-domain.com. In auth-proxy-keycloak-config.yaml I have encryption key, and client_id. The keycloak client is setup for public access and standard flow (hence no client_secret needed, I presume). I have fiddled with the various uri settings, and also put in web origins "*" for CORS for testing.
When I try a protected url in the browser, I see:
no session found in request, redirecting for authorization {"error": "authentication session not found"}
in the proxy logs, and it redirects me to /oauth/authorize, not to https://auth.my-domain.com/auth/realms/my-realm/protocol/openid-connect/auth where I think it should redirect me.
UPDATE -- as #jan-garaj noted in comment to answer, /oauth/* shouldn't have been whitelisted. (I got that from a possibly mistaken interpretation of someone else's answer.) I then had to make the cookie not http-only, and finally hit on this issue - Keycloak-gatekeeper: 'aud' claim and 'client_id' do not match ... after that it works!
From the Louketo-proxy doc:
/oauth/authorize is authentication endpoint which will generate the OpenID redirect to the provider
So that redirect is correct. It is louketo-proxy endpoint. It is not request for your app, it will be processed by louketo-proxy. It will generate another redirect to your IDP, where user needs to login.
Off topic:
you really need confidential client and client secret for authorization code flow
web origins "*" for CORS is correct only for http protocol, explicit origin specification is needed for https

Facebook - Curl Error SSL_CACERT SSL certificate

I am getting "Curl Error : SSL_CACERT SSL certificate problem: unable to get local issuer certificate" when asking Facebook to scrape my page over https. How can I fix this so that Facebook can scrape my page without errors?
The page is hosted via Apache 2.4 proxying to IIS 10. Apache handles all certificates and IIS is on the local network. My page is running asp code (so no php) and solutions similar to these: edit the php.ini file or adding curl.pem to php folder will not work fix my problem ... or so I think?!?
IIS has no certificate installed.
I do have extension=php_curl.dll enabled -- and extension_dir = 'C:\64bit\php-7.0.6-Win32-VC14-x64\ext' defined in my php.ini file. I followed these steps to install Curl on Windows. And phpinfo.php confirms that cURL is enabled (cURL Information 7.47.1).
My proxy setup in my Apache config file is:
<IfModule mod_proxy.c>
ProxyRequests Off
ProxyPass / http://192.168.1.101:88/com_ssl/
ProxyPassReverse / http://192.168.1.101:88/com_ssl/
RewriteRule ^(.+)$ https://www.domainname.com/$1 [P,L]
</IfModule>
I have no RequestHeader defined in my Apache proxy config file, such as suggested here in Step 10:
RequestHeader set "X-RP-UNIQUE-ID" "%{UNIQUE_ID}e"
RequestHeader set "X-RP-REMOTE-USER" "%{REMOTE_USER}e"
RequestHeader set "X-RP-SSL-PROTOCOL" "%{SSL_PROTOCOL}s"
RequestHeader set "X-RP-SSL-CIPHER" "%{SSL_CIPHER}s"
Is this what is missing to fix the error?
"unable to get local issuer certificate" is almost always the error message you get when the server doesn't provide an intermediate certificate as it should in the TLS handshake, and as WizKid suggests, running the ssllabs test against the server will indeed tell you if that is the case.
If you are using nodejs server and getting this error 'Curl Error SSL_CACERT SSL certificate' then you need to add your CA along with your SSL CRT.
var fs = require('fs');
var https = require('https');
var options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-crt.pem'),
ca: fs.readFileSync('ca-crt.pem'), // <= Add This
};
https.createServer(options, function (req, res) {
console.log(new Date()+' '+
req.connection.remoteAddress+' '+
req.method+' '+req.url);
res.writeHead(200);
res.end("hello world\n");
}).listen(4433);
This may not have been the case at the time but I will add this info in case others encounter the same issue.
If you are using a CDN, like cloudflare, it is important to set up your SSL before adding to cloudflare as it can generate issues.
It is also important to ensure that all domains are correctly annotated in the DNS control of cloudflare, otherwise you may end up serving your main domain via cloudflare and your subdomain(s) directly from your server. Whilst this wont matter much to the user (still shows secure, still have access, still passes SSL tests) it may flag issues with sharing apps onto social media. Basically, I replicated the error by splitting the DNS setup as above and achieved the flagged error as highlighted by the op. Then I added the DNS for the subdomain into cloudflare, tested a few hours later (after resetting the page in debudder: https://developers.facebook.com/tools/debug/sharing/?q=https%3A%2F%2Fus.icalculator.info%2Fterminology%2Fus-tax-tables%2F2019%2Fvirginia.html). and, hey presto, the error goes. So, if you encounter that issue and you use cloudflare, that is something to check you have set up correctly.