I have angularjs application where users enter data that is saved to database, then on server side it is compiled into pdf file. All access requires appropriate authentication headers in place. After needed data is filled a user presses button to save data and then to retrieve pdf file. Optimally, I call $window.open(url_generating_pdf
) in my angularjs app. This works well and opens in another window, but how to add authentication header to this $window
request? In my understanding I cannot download pdf, and print it with ajax, so I am missing this authentication. Or would there be other ways to call url from server, and make the file open in another window?

- 5,004
- 4
- 32
- 50

- 263
- 1
- 4
- 10
-
There is an open issue for adding support for headers to the window.open function in the HTML standard. Please voice your opinions and needs on there. [https://github.com/whatwg/html/issues/7810](https://github.com/whatwg/html/issues/7810) – Dan Apr 14 '22 at 21:36
-
I did add my support there, and I like it – user2576168 Apr 21 '22 at 13:02
3 Answers
I think I should update this old question with a correct and secure answer.
You can not add any headers in the HTTP GET request performed by window.open.
The secure way to make an authenticated request is to set the authentication token into a request header, and avoid exposing it into the URL, as my previous answer suggested (I have learned a some things since then).
To download a PDF (or any other binary data) from an authenticated server with AngularJS you should:
- Make an HTTP GET request to the resource sending the authentication token in a header, setting its responseType to a binary data type, for example blob or arraybuffer.
- Download the binary data in a file using the "Save As" dialog from the browser, usually creating a download link for the binary data and clicking it.
I hope this answer to clear doubts on this question and provides a secure way to download a resource from an authenticated REST API.

- 861
- 2
- 10
- 19
I think you can add this authentication parameters in URL and do a GET in your server side
//Add authentication headers as params
var params = {
access_token: 'An access_token',
other_header: 'other_header'
};
//Add authentication headers in URL
var url = [url_generating_pdf, $.param(params)].join('?');
//Open window
window.open(url);

- 861
- 2
- 10
- 19
-
4In the end, I went around the problem. I made standard $http.get for the pdf. I return short lived url back to get call that allows unauthenticated download with window.open to a new window. Your solution would have been workable as well – user2576168 Oct 24 '15 at 15:07
-
12@hmartos Sending your token in the URL exposes it to be used by anybody eavesdropping on your packets sent to the server. The URL is never encrypted and therefore can be seen by anybody. Take care never to expose your token. In the words of Gandalf: "Keep it secret, keep it safe." – JFarr Nov 23 '16 at 16:15
-
1Thanks for the advice @JFarr, any idea of how to pass the token to API keeping it secret? – hmartos Nov 24 '16 at 13:11
-
3After researching a little bit, I have found that query strings over https are secured, anyway it is not a good idea to send any sensitive data in URL (see http://stackoverflow.com/questions/323200/is-an-https-query-string-secure). So I think the best choice is to send this token in a request header (http://stackoverflow.com/questions/187655/are-https-headers-encrypted) – hmartos Nov 24 '16 at 16:30
-
1For anybody looking for a secure approach to this problem, I strongly recommend to check my latest answer to this question. – hmartos Feb 23 '19 at 09:02
-
3This doesn't answer the question. The token is added as a query param instead of respecting the original criteria of adding it as a header. – Tristan Nov 04 '19 at 01:04
You could call your secured api with token in header and responseType to blob and parse your response in following way and hope you will view your pdf in browser for chrome and firefox.
var ieEDGE = navigator.userAgent.match(/Edge/g);
var ie = navigator.userAgent.match(/.NET/g); // IE 11+
var oldIE = navigator.userAgent.match(/MSIE/g);
var blob = new window.Blob([response], { type: 'application/pdf' });
if (ie || oldIE || ieEDGE) {
window.navigator.msSaveBlob(blob, fileName);
}
else {
var fileURL = URL.createObjectURL(blob);
window.open(fileURL);
}

- 578
- 8
- 14