http-proxy-middleware to modify port only - http-proxy-middleware

I'm using an advanced proxy in create-react-app which uses http-proxy-middleware. I'd like to pass through the domain and modify the port only for all requests.
I believe in create-react-app I must use the shorthand:
app.use(
'/api',
proxy({ target: 'http://www.example.org:8000' })
)
Is there a way I can pass through all requests to API so that the domain is unchanged but the port is 8000?

I found that this approach works:
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
proxy('/api', {
target: 'https://[::1]:8000',
secure: false,
})
)
}
As a way to proxy https://<any-domain>:3000/api to https://<any-domain>:8000, as mentioned in a few issues on the http-proxy-middleware. However, this seems a little hacky, and I can find no reference to this in the docs.
If anyone has any additional feedback on this, I'd be very interested to read more.
Note that ::1 is just the IPv6 loopback address.

Related

Is it impossible to set a domain of localhost cookie remotely from a backend?

I've already checked out these two SO questions:
Can I use localhost as the domain when setting an HTTP cookie?
Setting a cookie from a remote domain for local development
But I don't want to edit my HOSTS file and setting a wildcard domain doesn't help me.
I've used node.js, but it should be programming language agnostic...
So my problem is the following:
I wanna work on my Angular frontend on https://localhost:4200 (and possibly http://localhost:4200) and reach my backend by getting access to it. Obviously I have to implement CORS rules for that, hence I've implemented the following CORS rules in the Node.js backend:
const allowedOrigins = environment.header;
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
where allowedOrigins is an array that contains the following:
environment.header = ['https://localhost:4200', 'http://localhost:4200', 'http://test.example.org', 'https://test.example.org'];
The problem at hand is that when I go to work on my Angular frontend locally it does not send the cookie to the backend for some reason (maybe this kind of connection is simply not allowed by some RFC???), hence my JWT checking mechanism throws 403 Forbidden after logging in instantly.
My JWT check function looks like this:
if (req.headers.origin === 'https://localhost:4200' || 'http://localhost:4200')
orig = 'localhost';
else
orig = req.headers.origin;
res.cookie(
'access_token', 'Bearer ' + token, {
//domain: 'localhost',
domain: orig,
path: '/',
expires: new Date(Date.now() + 900000), // cookie will be removed after 15 mins
httpOnly: true // in production also add secure: true
})
I need to do this to work on my Angular frontend locally and the backend has a connection to another server, which works only locally for now...
withCredentials is of course true (so the JWT cookie is being sent with), so that's not the problem in my codebase.
UPDATE
Ok so I've figured out that req.headers.origin is usually undefined..
UPDATE 2
Changed req.headers.origin to req.headers.host, but still it doesn't work
I needed to add the following properties to the res.cookie for it to work:
sameSite: 'none', secure: true
Then I enabled third-party cookies in Incognito mode and it worked for me.
Case closed.

How to rewrite request path using http-proxy-middleware in a react app?

I am using http-proxy-middleware in my react app, where I have a setup like this:
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function(app) {
app.use(
"/api/v1",
createProxyMiddleware({
target: "https:test.com/",
changeOrigin: true
})
);
};
Some api requests of my applications has request url as:
http://localhost:3000/products-and-details/api/v1/proxy/trend/api/v1/listProducts
which I want to change it to:
http://localhost:3000/api/v1/proxy/trend/api/v1/listProducts.
To achieve this I am modifying request paths before requests are send to the target using pathRewrite as below:
pathRewrite: {
'^/products-and-details': ''
}
However this doesn't seem to work and the request url remains the same with no changes. Can anyone please help to point out what am I doing wrong here?
Edit: My http-proxy-middleware dependency has a version ^2.0.3
My senior colleague helped me to fix this. It seemed that the request, http://localhost:3000/products-and-details/api/v1/proxy/trend/api/v1/listProducts was not at all intercepted by the proxy. Hence, to intercept those requests we have to make sure to include it in the context for our proxy middleware.
So, in my case it was as described below:
app.use(["/api/v1", "/products-and-details/api/v1"])
And then use PathRewrite to modify request paths before the actual request is made to server as depicted below:
pathRewrite: {"/products-and-details": ""}

nodejs keycloak-connect-graphql not working while in docker

I have hit an issue that I have struggled to figure out for the last little while regarding docker. Here is a shortened version of the story
In my development environment (everything is running on localhost), code works great, whenever I add my authorization token in my headers keycloak-connect detects it and works as usual. The problem occurs when I use it in docker and add custom network interfaces.
When the docker container boots up, I have it connect to keycloak via http://keycloak:8080/auth and generate the realm. That works fine, not an issue, thus I know that the keycloak network is up and running as expected. I am able to remote into the container, communicate with keycloak, get a token and etc...
In my graphql application, I use keycloak-connect-graphql to set the context of the graphql application which in turn uses keycloak-connect to set up all the headers. The problem is, that keycloak-connect-graphql tells me that there is no header.If I simply print out the request, I can clearly tell that there is a token being passed in, it's just that for some reason, keycloak-connect-graphql/keycloak-connect does not want to set it because I am using a different network besides localhost.
I was actually able to side-step this problem in production by setting the keycloak url to be a the public url (https://keycloak.DOMAINNAME.com) which makes absolutely no sense to me because http://keycloak:8080/auth does not work. I have digged through keycloak-connect and the keycloak-connect-graphql code and I could not find anything relating to a CORS issue or something else suspicious. If anyone has any ideas please let me know. This bug has been driving me crazy.
Code snippet:
keycloak configuration (app.config)
keycloak: {
realm: process.env.KEYCLOAK_REALM,
'auth-server-url': 'http://keycloak:8080/auth',
'ssl-required': 'none',
resource: process.env.KEYCLOAK_RESOURCE,
'public-client': true,
'use-resource-role-mappings': true,
'confidential-port': 0,
},
configurekeycloak.js
function configureKeycloak(app, graphqlPath) {
const keycloakConfig = require('../config/app.config').keycloak;
const memoryStore = new session.MemoryStore();
app.use(
session({
secret:
process.env.SESSION_SECRET_STRING || 'this should be a long secret',
resave: false,
saveUninitialized: true,
store: memoryStore,
}),
);
const keycloak = new Keycloak(
{
store: memoryStore,
},
keycloakConfig,
);
// Install general keycloak middleware
app.use(
keycloak.middleware({
admin: graphqlPath,
}),
);
// Protect the main route for all graphql services
// Disable unauthenticated access
app.use(graphqlPath, keycloak.middleware());
return { keycloak };
}
index.js
// perform the standard keycloak-connect middleware setup on our app
const { keycloak } = configureKeycloak(app, graphqlPath);
// Ensure entire GraphQL Api can only be accessed by authenticated users
app.use(playgroundPath, keycloak.protect());
const server = new ApolloServer({
gateway,
// uploads: false,
// Apollo Graph Manager (previously known as Apollo Engine)
// When enabled and an `ENGINE_API_KEY` is set in the environment,
// provides metrics, schema management and trace reporting.
engine: false,
// Subscriptions are unsupported but planned for a future Gateway version.
subscriptions: false,
// Disable default playground
playground: true,
context: ({ req }) => {
return {
kauth: new KeycloakContext({ req }),
};
},
// Tracing must be enabled for this plugin to add the headers
tracing: true,
// Register the plugin
plugins: [ServerTimingPlugin],
});
Edit:
setting network_mode to host fixes the issue, but I much prefer using dockers integrated networks rather than using network_mode host, especially for production
Edit 2:
I was able to reproduce the error in my local development environment (without shelling into docker and then debugging from there). I was able to do this buy using the IP address provided by docker. This yields the same results. I have narrowed the issue down to keycloak-connect, which for some reason, does no want to connect to keycloak or something. Still not sure

Proxy issue on calling express server from react server

Hey guys i was just working out on Proxy for calling nodejs server from react server, so after adding "proxy": "http://localhost:5000/"
to my package.json file in react i was able to redirect to localhost:5000 (which is running my node server) but it seems that Proxy only works with fetch and axios as
axios.get("/api/currentuser")
redirects me to localhost:5000
but then when i try this on anchor tag like
<li>Login with google</li>
it doesn't takes me to localhost:5000
so is there any way that sometimes working with tag if i need to stay at localhost:3000i should be there and whenever i need i can go to localhost:5000 ???
cause not for all anchor tag i need to redirect to localhost:5000
According to this post and react documentation you can use the file setupProxy.js to redirect requests based on certain criteria to a proxy and it also seems to work for href property.
You would have to adapt the example code:
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use('/api', proxy({
target: 'http://localhost:5000',
changeOrigin: true,
}));
};
to your requirements. You can use pattern matching on the api paths, so it should not be a problem. Hope this helps! :)

Express session-cookie not being sent on openshift with https and secure flag

Got a strange issue, I am using Express and in development we use http and have secure: false for the session cookie, however now we are moving to openshift we have turned https on thinking it would be a simple endeavour but our cookies are not being sent back with the responses. If however we turn off https and revert back to http on openshift it works fine and cookies are sent.
So here is an example of what the cookie config looks like:
var setupSession = function() {
var sessionConfig = {
secret: environmentVars.cookie.secret,
name: environmentVars.cookie.name,
maxAge: environmentVars.cookie.expiry,
domain: environmentVars.cookie.domain,
httpOnly: true,
secure: environmentVars.cookie.secure, // true when using https
secureProxy: environmentVars.cookie.secure, // true when using https
signed: true
};
app.set('trust proxy', 1); // Just added this, still no luck
app.use(session(sessionConfig));
};
So the above is run when the app starts up and as noted in the comments when we are using a secure connection the environment vars are set for us, and when the above is used in conjunction with HTTPS no cookie is sent back from express, however openshift cookies are sent back, like the gears one etc. Again with http and disabling the secure stuff it works fine we all get cookies and rejoice. All responses work and data is sent back its just the set-cookie header is missing for the apps cookies (but as mentioned not openshift ones).
So the actual certificate is not setup within nodejs it is setup on openshift as an alias with a certificate applied. So express really has no idea it is being run in https other than the environmental vars it is passed and the port it is provided by the gear that is running it.
So has anyone else had anything similar or has any ideas on what we can try to solve the problem or diagnose it? I did some reading and people suggested trying the trust proxy and secureProxy, which has been done but still no luck.
So it turns out I was just being an idiot, it should look like:
var setupSession = function() {
var sessionConfig = {
secret: environmentVars.cookie.secret,
name: environmentVars.cookie.name,
maxAge: environmentVars.cookie.expiry,
domain: environmentVars.cookie.domain,
httpOnly: true,
secureProxy: environmentVars.cookie.secure, // true when using https
signed: true,
cookie: {
secure: environmentVars.cookie.secure, // true when using https
}
};
app.set('trust proxy', 1); // Just added this, still no luck
app.use(session(sessionConfig));
};
All works now :)
I had similar problem with express-session and after many trials the culprit for me was setting cookie.domain. Browsers wouldn't save the cookie.
This is how I was setting the value:
cookie: {
...
domain: process.env.OPENSHIFT_CLOUD_DOMAIN,
...
}
Hope it helps anyone going through the same, since at the time this is the best suited stackoverflow question to share this.

Resources