Download anchor link with authorization header

31,443

Update 2022

Apparently, it works with XHR now as shown in this answer. Thanks goes to Jamie Pete for the reference.


Original answer

This not possible, because the only way to add HTTP headers is using the XHR, but XHR cannot be used to download files.

You could however use cookies to do that.

  1. Just set the cookie, with a returned value from the server.
  2. Wait till the user clicks the link.
  3. Invalidate the cookie after the user clicked the link.
Share:
31,443
Erik
Author by

Erik

http://erikevenson.net

Updated on April 19, 2022

Comments

  • Erik
    Erik about 2 years

    I have a link that I would like to add to my javascript (Marionette/Backbone) single page application that will download an Excel file to the user's local drive via the browser's file save. A typical HTTP request would be:

    GET /api/v1/objects/?format=xls HTTP/1.1
    Authorization: ApiKey username:apikey
    Host: api.example.com
    Connection: close
    User-Agent: Paw 2.0.5 (Macintosh; Mac OS X 10.9.2; en_US)
    Content-Length: 0
    

    Which results in the following typical response:

    HTTP/1.1 200 OK
    Server: gunicorn/18.0
    Date: Tue, 06 May 2014 03:09:02 GMT
    Connection: close
    Transfer-Encoding: chunked
    Vary: Accept
    Content-Type: application/vnd.ms-excel
    Content-Disposition: attachment; filename="filename.xls"
    Cache-Control: no-cache
    
    <<CONTENT HERE>>>
    

    I'd like to do this with a simple anchor element styled as a button as this would invoke the browser's file storage machinery. Something similar to:

    <a href="/api/v1/objects/?format=xls" class="btn btn-primary pull-right">Download to Excel file</a>
    

    I'm not clear on how I get the authorization header to be passed when doing this via an anchor link -- or perhaps I'm just not thinking and there is a better way.

    My backend is a Django web app using Tastypie.

  • Erik
    Erik almost 10 years
    I suspected this was the case. Just wanted to be sure. I guess I will fall back on some sort of session cookie arrangement similar to what you are suggesting. Thanks!
  • Ashok Gurram
    Ashok Gurram over 5 years
    What is the use of setting cookie to download file on link click.
  • Artjom B.
    Artjom B. over 5 years
    @AshokGurram No idea what I was thinking or what I meant. It could be that I suggested to refactor the server code to use cookies instead of a usename and API key combination which is invalidated so that future requests would not have that cookie, but I'm not sure. Maybe there was something lost in translation. Anyway, there is a better solution as Robert mentioned.
  • Ashok Gurram
    Ashok Gurram over 5 years
    Thanks for your Response. I have 5 cookies in the browser but on hitting api, only 3 cookies are being sent to back end, 2 of remaining cookies are getting lost. Any Idea? I have checked in header, It is sending 5 cookies but on checking in backend java only 3 cookies are exist.
  • Artjom B.
    Artjom B. over 5 years
    @AshokGurram If you've checked the developer tools in your browser that the cookies are sent in the request that you expect, then this is really a server issue. The Java server ecosystem is quite extensive and you'd have to be more specific, but even then I'm not sure I can answer. Make sure that you're checking the cookies from the correct request on the server side.
  • j0nd0n7
    j0nd0n7 over 4 years
    I would generate a temporal download JWT token (5 minutes life span) from a new api operation and then add an url parameter to provide it in the download resource.
  • Wenfang Du
    Wenfang Du over 3 years
    XHR or Fetch
  • ssougnez
    ssougnez over 2 years
    That does not seem very secure, does it? Headers are encrypted by HTTPS but URL isn't if I'm not mistaken so it would be very easy for a man in the middle to get the access token.
  • haraldfw
    haraldfw over 2 years
    Do not do this. Request URLs are no place for auth-information. URLs are locators, they should define where a resource is, not what user can access them. If you for some reason have to put the token as part of the URL-string use a query parameter instead. FYI both the path and query string is encrypted under HTTPS, but they are more likely to be logged by backends/APIs or be saved by a browser in the history or similar, so it is usually less secure than using a header or the request body.
  • Jamie Pate
    Jamie Pate about 2 years
    According to this it can be done using XHR now stackoverflow.com/a/44435573/193232 If you set the XMLHttpRequest.responseType property to 'blob' before sending the request, then when you get the response back, it will be represented as a blob. You can then save the blob to a temporary file and navigate to it.
  • Jamie Pate
    Jamie Pate about 2 years
    there are also npm solutions to save the blob npmjs.com/package/file-saver but it's no longer an href...