Redirect in Flask - pass a custom header in the request to target - python-3.x

TLDR; How do I set a custom HTTP request header in redirect?
Below code redirects to an external service but fails to pass 'Authorization' request header to target. I can see the header in response before redirect happens - can it be forwarded somehow?
#app.route('/external_page')
def external_page():
if not request.cookies.get('id_token'):
return flask.redirect(flask.url_for('login',_external=True,_scheme=SCHEME))
response = flask.redirect(flask.url_for('https://external_service_url/v1/ui'))
response.headers['Authorization'] = 'token_id'
return response
Answer:
It's not possible, in HTTP and not in any framework.
The only way for a site to instruct a browser to issue an HTTP request
with a custom header is to use Javascript and the XMLHttpRequest
object. And it needs CORS implemented on the target server to allow
such ajax requests.
Source: Redirect to page and send custom HTTP headers

It's not possible
See Redirect to page and send custom HTTP headers
The only way for a site to instruct a browser to issue an HTTP request
with a custom header is to use Javascript and the XMLHttpRequest
object. And it needs CORS implemented on the target server to allow
such ajax requests.

Related

NodeJS: header authorization missing from redirect using res.writeHead

I want to redirect an HTTP request to another NodeJS server.
I am using the res.writeHead in order to redirect the request.
Code alternative 1:
let headers = Object.assign({},req.headers)
await Object.entries(headers).forEach(async ([header,value]) => {
await res.setHeader(header,value)
})
await res.setHeader('Location',ENV_CONFIG.ENV_US_URL + req.url)
res.writeHead( 307 );
res.end();
code alternative 2:
let headers = Object.assign({},req.headers)
headers['Location'] = ENV_CONFIG.ENV_US_URL + req.url
res.writeHead( 307, {...headers} );
res.end();
code alternative 3:
let headers = Object.assign({},req.headers)
res.writeHead( 307, {'Location': ENV_CONFIG.ENV_US_URL + req.url,...headers} );
res.end();
The three alternatives deliver the same results.
The res headers do include the authorization header before it sent to the other NodeJS server.
When the "new" request arrives to the other NodeJS server, the authorization header is missing
The request header DO contain the authorization header.
why would the authorization header fall there?
BTW. I tried to set the value of the authorization header in some custom header, it went missing as well.
Headers like auth headers and other custom headers are NOT preserved by the browser when you do a redirect. The browser forms a new request to the location you specified in the redirect response and builds that new request with default headers, not with the headers from your redirect response. It is as if the user typed the redirected URL into the browser URL bar and the browser created a new, default request to that new URL.
You will need to pass information to the redirected request either via the URL path, via query parameters or via a cookie. Query parameters and the URL path will always be present on the redirected request and cookies will be present if the cookie is set on the domain of the redirected target.
When the "new" request arrives to the other NodeJS server, the authorization header is missing
Headers are not preserved when redirecting the browser. The browser creates a new request with default headers to the location specified in the redirect. Any information you want to communicate to the new target must be either in the redirect URL (path or query parameters) or in a cookie that is set on the target domain.

Why is my header not being set on redirect?

I have an express route. I set a header and a cookie and then I redirect.
router.get("/callback", async (req, res) => {
res.cookie("token", token, {
maxAge: COOKIE_EXPIRATION_MILLISECONDS
});
res.header("TEST", "HEADER");
res.redirect("/test");
});
When I hit /test, token is set and available. I do not have a header named TEST. Why do I not have the header? How do I pass the header through the redirect?
Your header is likely being sent with the response, but you won't see that header when the browser actually follows the redirect and then requests the new URL. Browsers don't do that. Remember, when you do res.redirect(), it sends a response with a 302 status and a location header. The browser sees that 302 and reads the location header and then makes a new browser request to your server for the redirected location. Headers from the previous response are NOT added to the new request for the redirected location.
The usual ways to pass data like this to a redirected requests are:
Put it in the query string for the redirected URL as a parameter. Your server will then see that query string when the redirected requests comes in.
Set a cookie. Your server can then look at the cookie when the redirected request comes in.
Set data in a server-side session object that can be accessed on the next request. Your server can then look at the session when the redirected request comes in.
Only the first option above (query parameter) is entirely safe because the others can get confused about which request the data belongs to if there are other requests coming in from that same user.

Does any browser implementation uses full url path in Origin header in an ajax request?

I'm talking about a CORS preflight HTTP request by the OPTIONS method which is sent by default by the browser before the actual request. In that request is it possible to make Orgin header to include the full url path?
OPTIONS / HTTP/1.1
Host: example.com
Origin: http://www.example.com/blah
I want my page to send full url in Origin header. Is there any way to trick the browser to do so?
you can always pass this value on the ajax parameters using something like:
$.ajax(url, {
fullOrigin: window.location.href
}
)
like #Robby Cornelisse said - most servers will hold REFERER server variable with this value.
The browser will send a REFERER header containing the full URL with your AJAX request.
In the screenshot below, I just used the console to send an AJAX request from this page. Notice the Referer header.
No, it's not possible. Origin is a scheme, domain and port parts of an URI by definition.
One option is to send current document URI to server using query part of request URI. You can use code below to change URI of every cross origin request on your page:
window.addLocation = function( uri ) {
var parser = document.createElement('a');
parser.href = uri;
var and = parser.search ? "&" : "";
parser.search = parser.search + and + "madeBy=" + window.location;
return parser.href;
};
var xhr = new XMLHttpRequest();
xhr.open( "GET", window.addLocation( originalUri ), true );
Note that current page URI may contain sensitive information, and that browser identifies HTTP Cache entries by URI including query.
For more information check:
Origin header page on MDN
Referer header section in HTTP 1.1 specification
URL Parsing gist by jlong
HTTP access control (CORS) page on MDN

ContentType is null when making Get requests using ServiceStack JsonServiceClient

In my integration tests, ContentType is null when I make Get requests using ServiceStack's JsonServiceClient. However all the Post requests have a ContentType. Is it excluded on purpose? ie. Do I need a content type for http get requests?
Is there a way I can set the ContentType using this client?
There is no Content-Type for GET Requests since it doesn't have a Request body.
The Content-Type on the Request Header specifies what format the Request Body is in, likewise when on the Response Body specifies what format the Response Body is in.
You may instead be after the Accept HTTP Request Header which tells the server the preferred Content Types it would like the Response in.

How to send node.js http request via proxy (using require('http').request method)

Probably related to How can I use an http proxy with node.js http.Client?
I've read this post, and tried it here.
https://gist.github.com/lessmind/5704519
the request function sends a request to specify url, print the request options and page body, when it got a proxy param, it'll parse it and set into the request options as this post said.
But when I tried it on http://showip.net/, the returned ip are the same with proxy or not.
Did I make anything wrong? Or any other way to send a request via proxy?
According to
http://nodejs.org/api/http.html#http_http_request_options_callback
hostname: To support url.parse() hostname is preferred over host
Should add this line when overwriting proxy informations.
options.hostname = proxy.hostname;

Resources