Node- / ExpressJS - Could not obtain grant code: unable to get local issuer certificate - node.js

I'm building a WebApp with Node- & ExpressJS. Currently I'm trying to connect my app to our company's Keycloak with the keycloak-connect module. I configured it as mentioned in different tutorials and it works (atleast mostly).
When I connect to my WebApp, I receive the keycloak login screen and the login procedure is successful (session created on keycloak). After the login procedure and the redirect I receive an "Access denied" error and in the logs "Could not obtain grant code: unable to get local issuer certificate".
WebApp runs on port 443 with valid certificates
I've googled everything I could and tried following solutions:
-- Disable rejecting unauthorized TLS --
Disabled TLS Rejection for unauthorized certificates with the node envorinment variable:
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
Works but isn't very secure...
Log.
-- Add an extra CA certificate --
Installed dotenv module and set following env variable in .env file:
NODE_EXTRA_CA_CERTS='/etc/pki/tls/cert.pem' (& ca-bundle.crt)
Included it in app.js with "require('dotenv').config();", doesn't work... Also tried to set it as a system environment variable with export.
It stands behind a proxy but I also configured express to trust all proxies with "app.set('trust proxy', true);".
-- Versions --
Node - v16.13.1
Express - ~4.16.1
Keycloak-connect - ^16.1.1
I've seen this problem on many different pages and they're mostly not fully resolved... Would be nice to find a solution for this problem.
Thanks in advance! :)
Yannic

Well I've found a solution and it works perfectly!
This comment on a GitHub issue describes, how to send ca files with the HTTPS server from NodeJS.
You can enter your ca files / bundles in an array:
const trustedCa = [
'/etc/pki/tls/certs/ca-bundle.crt',
'/etc/pki/tls/cert.pem'
];
Then read them with fileSync and set them as the globalAgent.options.ca option for the HTTPS server:
https.globalAgent.options.ca = [];
for (const ca of trustedCa) {
https.globalAgent.options.ca.push(fs.readFileSync(ca));
}
And that's all that needs to be done! Now I can login via Keycloak and it successfully redirects me to my WebApp without any errors.
Hopefully this helps.
Yannic

Related

How can I setup NODE_TLS for SSR Angular on Azure?

I have this SSR Angular web application that when I run (locally and production) I get the following warning
(node:6172) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
That's because I have the following line on my server (express-engine) file
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
If I remove that line, the requests to my API (HttpClient) will not work, giving the following error
'Http failure response for https://localhost:5000/: 0 Unknown Error'
So, how can I fix this in any environment? What could I be doing not to ignore the warning but set it right so I can keep the requests working and not using NODE_TLS_REJECT_UNAUTHORIZED?
Angular Universal does not wait for api/http request before render

Cannot read property 'NODE_ENV' of undefined in nodejs on https SSL

I have install the ssl certificate in my angular and nodejs project. but after installing the certificate i am unable to login into my application. My main index.js file is running perfectly, but when i am tried to login from my application, it showingn me 500 (Internal Server Error) with a message (Cannot read property 'NODE_ENV' of undefined). I am showing you the localhost but the same problem is coming on production.Please help me out here, how can i fix it.
My error image of application
My nodejs console working picture
It's not HTTPS SSL problem.
Seems that the problem is on the file which defines a handler for POST /login, attach this file for more details.

Icecast 2 and SSL

I am trying to make work icecast 2 and my letsencrypt SSL with no luck. So far what I did is built icecast 2 with openssl support and I also made it run but it always give the next error in the log file.
[2018-03-15 12:48:21] WARN connection/get_ssl_certificate Invalid private key file /usr/local/icecast/share/fullchain.pem
[2018-03-15 12:48:21] INFO connection/get_ssl_certificate No SSL capability on any configured ports
I have set these cert files readable by user: richard and of course I am also running the server itself with the richard user.
Maybe you have any idea what is wrong?
You may also see my config file here:
<listen-socket>
<port>8443</port>
<ssl>1</ssl>
</listen-socket>
In the path section I have set the ssl-certificate part to the SSL.
<ssl-certificate>/usr/local/icecast/share/icecast/fullchain.pem</ssl-certificate>
Nothing so far. The server itself is starting on the port, however when visiting it through https:// it just doesn't load. with http:// the port (8443) works fine.
Any help appricated.
Actually, I solved the issue myself.
The problem was the SSL not the configurations. Seems the LetsEncrypt SSL that is generated (fullchain.pem) is not working correctly. So instead of using that, I have copied the content from cert.pem and privkey.pem and made a new file named icecast.pem and pasted both into one. (first cert and then the privkey) and now everything is works fine and secure!
I am a genius!!!
For the Icecast2 complete certificate, you can use the command:
cat /etc/letsencrypt/live/domain.com/fullcert.pem /etc/letsencrypt/live/domain.com/privkey.pem > /etc/icecast2/bundle.pem
This will concatenate and save both certificates to a single file called bundle.pem under icecast2 folder, to which you can point the icecast2 configuration.
I have also found this very helpful and complete guide for reference: https://mediarealm.com.au/articles/icecast-https-ssl-setup-lets-encrypt/
There is another way, by forwarding of Nginx, whose config is common on internet. So that the server only expose 80 and 443 port for http web. Then use letsencrypt for SSL of Nginx.

Cannot POST to express server from domain with SSL on it

I have an existing ssl certificate through LetsEncrypt for my domain. On the same server as my site I have an express app running at port :8080. Before adding the SSL to the domain I was able to make requests to http://domainname:8080.com. Now that the domain making the requests is https it obviously can't make those requests. If I instead make requests to https://domainname:8080.com, I get no response and instead get a timeout error.
I have attempted to curl -X -POST on the server manually and it returns (35) gnutls_handshake() failed: The TLS connection was non-properly terminated. If I however run the same command pointing to the non https domain it executes correctly. I also tried installing the https modules for express and pointing it to the same certs I'm using for the domain. For all my effort I cannot get this to work. What am I missing here? I want to make requests to a port on the same server that is serving my app.
Setup a reverse proxy in my nginx site config from the domain to the ip address the express server was running on. This solved all the issues I was having.

SSL handshake failure with node.js https

I have an API running with express using https. For testing, I've been using tinycert.org for the certificates, which work fine on my machine.
I'm using docker to package up the app, and docker-machine with docker-compose to run it on a digital ocean server.
When I try to connect with Chrome, I get ERR_SSL_VERSION_OR_CIPHER_MISMATCH. When running this with curl, I get a handshake failure: curl: (35) SSL peer handshake failed, the server most likely requires a client certificate to connect.
I tried to debug with Wireshark's SSL dissector, but it hasn't given me much more info: I can see the "Client Hello" and then the next frame is "Handshake Failure (40)".
I considered that maybe node on the docker container has no available ciphers, but it has a huge list, so it can't be that. I'm unsure as to what's going on and how to remedy it.
EDIT
Here's my createServer() block:
let app = express();
let httpsOpts = {
key: fs.readFileSync("./secure/key.pem"),
cert: fs.readFileSync("./secure/cert.pem")
};
let port = 8080;
https.createServer(httpsOpts, app).listen(port);
I've had this problem for a really long time too, there's a weird fix:
Don't convert your certs to .pem; it works fine as .crt and .key files.
Add ca: fs.readFileSync("path to CA bundle file") to the https options.
It looks like your server is only sending the top certificate and the CA bundle file has the intermediate and root certificates which you'll need for non-browser use.
IMPORTANT! Reinstall or update node to the latest version.
You can use sudo apt-get upgrade if you're on Linux (it may take a while).
Re-download your certificate or get a new one.
If you are acting as your own certificate authority it could be not recognizing / trusting the certificate, so try testing your site on ssllabs.com.
If you're using the http2 API try adding allowHTTP1: true to the options.

Resources