Get user-id from Caddy and CherryPy basic-auth - cherrypy

I'm using Caddy as a reverse proxy, feeding a web app on CherryPy. Caddy is handling basic-auth, and I would like to pass the username to the CherryPy app.
I've modified my Caddyfile like this:
my.example.com {
redir /data_tools /data_tools/
handle_path /data_tools/* {
import basic-auth
reverse_proxy data_tools:1234 {
header_down +X-WEBAUTH-USER={http.auth.user.id}
}
}
}
When I go to my.example.com/data_tools/ I see my header populated correctly. If I go to my.example.com/data_tools/index.html, the header is there, but it's empty.
I've tried to intercept the headers with different hooks in CherryPy, but my header doesn't show up there at all.
def show_headers():
print("Request")
print(json.dumps(cherrypy.request.headers, indent="\t"))
print("Response")
print(json.dumps(cherrypy.response.headers, indent="\t"))
cherrypy.tools.get_user = cherrypy.Tool('on_start_resource', show_headers)
^^^ Shows expected headers, but not my custom one.
Any suggestions?

I got help from the Caddy Forum.
In my caddyfile, this is what I had for the basic-auth section.
(basic-auth) {
basicauth / {
my-name XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
}
}
The / here makes it so that basicauth only applies to requests to exactly / and nothing else. Remove that to make it match all requests.
Once I did that, I could see the headers through CherryPy, although they didn't show in the developer tools of the browser.

Related

connection between angular and node

I have an angular app and I want to connect to node.js server. My question is how to do that? Do I have to write any code on my angular app to set the connection and then send the http request or just send the requests to the server? (I have all the API's ens points).
When I just send the request I get 404 error.
export class ApiConnectionService {
uri = "http://dev.cantinadigital.co.il:8080";
constructor(private http: HttpClient) { }
postContactUsMessage(message: Object): Observable<any> {
return this.http.post(${this.uri}/contactus, message);
}
}
If you have Angular app working for example on 'localhost:3000' and node server on 'localhost:5000' You have to send request to node server address. So if you want to get for example list of todo's you have to send 'GET' request to 'localhost:5000/todos'. But if it all works on one port, You just send request to '/todos' and that should work well.
You just send a request to your server.
For Example:
public doSomething(): Promise<any> {
var url = "localhost:8081/api/test";
return this.http.get(url, option).toPromise();
}
When you call the function, don't forget its asynchronous:
doSomething().then(result => ....)
Also you have to adjust your proxy settings, so you have to add an entry in proxy.conf.json
If you get a 404 maybe your server setup is not working. So maybe it would be best if you check with Postman, if you can reach your url.
I made a demo for you to how to deal with the Http calls and Api in angular and put you a comment in what you should change to work with your case:
https://stackblitz.com/edit/angular-service-intro?file=src%2Fapp%2Fapp.service.ts
Hope this helps you

Always redirect http traffic to https traffic in google app engine nodejs flex environment [duplicate]

I've followed the answer of this: Redirect from http to https in google cloud but it does not seem to be currently accurate any more. The anchor referenced ( https://cloud.google.com/appengine/docs/flexible/nodejs/configuring-your-app-with-app-yaml#security ) seems to have been removed but without a note of a replacement.
For reference, I am serving NodeJS over a Google App (flex) Engine. As per the answer I've got in my app.yaml:
handlers:
- url: /.*
script: IGNORED
secure: always
Since HTTPS is obviously terminated before it hits my Express engine (and redirection on there would be useless); how is it currently correctly implemented?
Potentially helpful, I have an external domain attached via the "Custom domains" tab in the console, and there is indeed a SSL certificate configured (so if a user manually goes to https://.com everything is fine)
The flexible environment does not current support handlers in the app.yaml. If you want https:// redirection, you have a few options:
Use helmet to do to HSTS stuff for you, and implement your own initial redirect.
I wrote a happy little library to always forces SSL on all routes for express yes-https
We are considering auto-redirecting all traffic to SSL by default. Do you think that would be a good thing for your apps?
Pulling Justin's yes-https library, I was able to get this to work:
var app = express();
app.use(function(req, res, next){
if (req.host != 'localhost' && req.get('X-Forwarded-Proto') == 'http') {
res.redirect(`https://${req.host}${req.url}`);
return;
}
app.router(req, res, next);
});
At first I thought I had to do that since I was on an appengine subdomain and couldn't use HSTS. Then I learned HSTS works fine for subdomains. :) Regardless, I thought people might want to see what the magic bit to use was if they didn't want to use yes-https for some reason.
Justin, auto-redirecting all traffic to SSL by default sounds great to me. I just spent hours trying to figure out how to do so before I found this post because I was trying to get my app to get Chrome's add to homescreen install banner as per https://developers.google.com/web/fundamentals/engage-and-retain/app-install-banners/.
GCP This should be as easy to just use the gcloud app cli and configure a header (Strict-Transport-Security) or redirect rule. Perhaps the push is to force us to Firebase Hosting instead which is forcing HTTPS already. For a quick solution for Single Page apps (static content) with React, Angular etc, we can use this JS snippet.
It ignores localhost environments. You can change localhost with a host name that you would like to exclude. It then redirects using https as protocol.
if ( location.host.indexOf("localhost") < 0 && location.protocol.toLowerCase() !== "https:"){
const url= `https://${location.host}`;
location.replace(url);
}

angular universal https problems

I have an angular universal app set up. I do POST requests on the server-side using localhost to pre-render my app and this works fine.
An example working url would be http://localhost:8000/api/get-info.
I've now put the app into production on an external url (apache server). I'm also using ssl.
Now when I try to do a POST request on the server-side to pre-render my app, I get back a response with status: 0, url: null (I'm assuming this means the connection was refused).
An example non-working url would be https://mywebsite.com/api/get-info.
What really stumps me is that when the app loads on the client, all HTTPS requests start working. So the problem is I cannot get the express server to send POST requests to my external url.
I've tested a post request on the server-side to a different website (twitter), and that seems to work fine as well. So i'm not entirely sure where I've gone wrong.
I already have CORS set to '*' as well.
Try using
http://localhost:8000/api/get-info
in production as well. Since your Angular app is rendered on the same server as your API is running, using localhost should just work fine. It doesn't matter if you are on an external URL.
I do something similar (its a GET but that shouldn't matter) with my translations:
if ( this.isServer ) {
translateLoader.setUrl( 'http://localhost:4000/assets/localization/' );
} else {
translateLoader.setUrl( 'assets/localization/' );
}
It works locally and in production (both server and client).
I just encountered this problem myself for two days. Please take a look at my comment on https://github.com/angular/universal/issues/856#issuecomment-426254727.
Basically what I did was I did a conditional check in Angular to see if the APP is running in browser or in server (rendered by Angular Universal), and change my API endpoint to actual IP in https or localhost in http accordingly. Also in my Nginx setting, I only redirect incoming request from browser to https by checking if the server_name is localhost.
Hope it helps!

HTTP to HTTPS redirection on App Engine Flexible

I've followed the answer of this: Redirect from http to https in google cloud but it does not seem to be currently accurate any more. The anchor referenced ( https://cloud.google.com/appengine/docs/flexible/nodejs/configuring-your-app-with-app-yaml#security ) seems to have been removed but without a note of a replacement.
For reference, I am serving NodeJS over a Google App (flex) Engine. As per the answer I've got in my app.yaml:
handlers:
- url: /.*
script: IGNORED
secure: always
Since HTTPS is obviously terminated before it hits my Express engine (and redirection on there would be useless); how is it currently correctly implemented?
Potentially helpful, I have an external domain attached via the "Custom domains" tab in the console, and there is indeed a SSL certificate configured (so if a user manually goes to https://.com everything is fine)
The flexible environment does not current support handlers in the app.yaml. If you want https:// redirection, you have a few options:
Use helmet to do to HSTS stuff for you, and implement your own initial redirect.
I wrote a happy little library to always forces SSL on all routes for express yes-https
We are considering auto-redirecting all traffic to SSL by default. Do you think that would be a good thing for your apps?
Pulling Justin's yes-https library, I was able to get this to work:
var app = express();
app.use(function(req, res, next){
if (req.host != 'localhost' && req.get('X-Forwarded-Proto') == 'http') {
res.redirect(`https://${req.host}${req.url}`);
return;
}
app.router(req, res, next);
});
At first I thought I had to do that since I was on an appengine subdomain and couldn't use HSTS. Then I learned HSTS works fine for subdomains. :) Regardless, I thought people might want to see what the magic bit to use was if they didn't want to use yes-https for some reason.
Justin, auto-redirecting all traffic to SSL by default sounds great to me. I just spent hours trying to figure out how to do so before I found this post because I was trying to get my app to get Chrome's add to homescreen install banner as per https://developers.google.com/web/fundamentals/engage-and-retain/app-install-banners/.
GCP This should be as easy to just use the gcloud app cli and configure a header (Strict-Transport-Security) or redirect rule. Perhaps the push is to force us to Firebase Hosting instead which is forcing HTTPS already. For a quick solution for Single Page apps (static content) with React, Angular etc, we can use this JS snippet.
It ignores localhost environments. You can change localhost with a host name that you would like to exclude. It then redirects using https as protocol.
if ( location.host.indexOf("localhost") < 0 && location.protocol.toLowerCase() !== "https:"){
const url= `https://${location.host}`;
location.replace(url);
}

Node reverse proxy basic routes issue

I have node-reverse-proxy set up like this:
var options = {
pathnameOnly: true,
router: {
'/myapp': '127.0.0.1:9000',
}
}
httpProxy.createServer(options).listen(8000);
The webapp at the root of 9000 has an index.html file with a stylesheet link like this:
<link rel="stylesheet" href="styles/blue.css">
When I hit localhost:9000 directly the html is loaded and the css is found. Then I hit it through the reverse proxy at localhost:8000/myapp, however I get an Error 404 because localhost:9000/styles/blue.css is not found, because the file is served apparently at localhost:9000/myapp/styles/blue.css.
The html of my app of course doesn't know about the reverse proxy so I can't fix this in the index.html. So I guess I'm missing something basic about the setup of the proxy??
I don't know if you've found a workaround for this by now, but I had the exact same problem and think I've worked it out.
When you hit the target endpoint directly localhost:9000 the path is sent through as /, ie just the root. Then when it requests the css etc, it resolves those as expected, from the root.
When you call via the proxy localhost:8000/myapp it routes /myapp to the target and then passes the target service / as the path, at which point it behaves exactly as above.
The problem here is actually at the browser. Because the path is specified as /myapp, it assumes that "myapp" is a filename. Then when it requests the css etc, it peels that back to the last slash and uses that as the base for all relative hrefs, which is why it then asks for /styles/blue.css and not /myapp/styles/blue.css. If you try browsing to localhost:8000/myapp/ - note the trailing slash - then it works because the browser now treats /myapp/ as a component of the path.
Obviously, you can't dictate that users must add the trailing slash. And you can't easily do much about it in the target service, if only because it doesn't see any difference, and anyway you don't want to have to repeat the same solution in every end service. So the answer seems to be to intercept it in the proxy.
This example works, though there might be a more robust way of implementing it. It looks out for cases where the last part of the path is probably a directory component, in which case the request is redirected to force the browser to re-issue it with a trailing slash. It makes that decision based on it not looking like a filename.ext or already having a trailing slash:
httpProxy.createServer(function(req, res, proxy) {
var parsed = url.parse(req.url);
if(!parsed.pathname.match(/(\w+\.\w+|\/)$/)) {
parsed.protocol = 'http';
parsed.host = req.headers.host;
parsed.pathname += '/';
res.writeHead(301, {Location: url.format(parsed)});
res.end();
} else {
proxy.proxyRequest(req, res);
}
}, options);

Resources