I am developing a ReactJS application that is calling REST APIs running in kubernetes. The setup is as follows:
The basic idea is the following:
ReactJS -> k8s ingress -> GO REST API
Now the problem starts when I try to set secure httpOnly cookies. Because the cookie needs to be secure, I created a self signed ssl certificate and applied it to be used by the ingress. I also enabled CORS settings in the ingress configuration. I also configured axios to not reject self signed certificates.
For some reason that is unknown to me I can't success in making the request.
Below are my relevant config files and code snippets:
k8s ingress:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: url-shortner-backend-services
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://localhost:4000"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
spec:
tls:
- secretName: urlshortner-local-tls
hosts:
- urlshortner.local
rules:
- host: urlshortner.local
http:
paths:
- path: /shortner(/|$)(.*)
backend:
serviceName: url-shortener-service
servicePort: 3000
- path: /auth(/|$)(.*)
backend:
serviceName: auth-service
servicePort: 3000
The react application start scripts:
PORT=4000 SSL_CRT_FILE=tls.crt SSL_KEY_FILE=tls.key react-scripts start
The axios code snippet that creates an axios instance that is used to issue a POST request
import axios from "axios";
import https from "https";
export default axios.create({
baseURL: 'https://urlshortner.local',
withCredentials: true,
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
});
When a POST request is made, I see the following error in the browser console/network tab even though when I first load the page I am accepting the certificate warning and adding it as a trusted certificate:
The end result that I would like to achieve is to be able to set a cookie and read the cookie on subsequent requests.
The cookie is being set as follows:
c.SetSameSite(http.SameSiteNoneMode)
c.SetCookie("token", resp.Token, 3600, "/", "localhost:4000", true, true)
What is missing? What am I doing wrong? Thanks in advance
I finally managed to fix this issue and the good news is that you don't need to create a self signed certificate.
The steps are the following:
Below are the relevant code snippets:
"scripts": {
"start": "PORT=4000 HOST=app.urlshortner.local react-scripts start",
}
notice the HOST environment variable, the PORT environment variable is optional, I'm using it because the default port 3000 is already taken.
127.0.0.1 app.urlshortner.local
192.168.99.106 urlshortner.local
note that 192.168.99.106 is my local minikube ip address.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: url-shortner-backend-services
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "http://app.urlshortner.local:4000"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
spec:
rules:
- host: urlshortner.local
http:
paths:
- path: /shortner(/|$)(.*)
backend:
serviceName: url-shortener-service
servicePort: 3000
- path: /auth(/|$)(.*)
backend:
serviceName: auth-service
servicePort: 3000
What matters here is the following:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "http://app.urlshortner.local:4000"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
import axios from "axios";
let baseURL = '';
if (process.env.NODE_ENV === 'development') {
baseURL = 'http://urlshortner.local';
}
export default axios.create({
baseURL,
withCredentials: true
});
c.SetCookie("token", resp.Token, 3600, "/", ".urlshortner.local", false, true)
note the domain used. It starts with a "."
I hope this helps someone.