Apache Cordova
  1. Apache Cordova
  2. CB-52

API: FileTransfer - Basic Authentication

    Details

    • Type: New Feature New Feature
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.6.0
    • Component/s: iOS
    • Labels:
      None

      Description

      reported at: https://github.com/phonegap/phonegap-iphone/issues/177
      by: https://github.com/berb

      (This feature request is platform-agnostic and has been posted here due to the comments in #phonegap)

      I'd appreciate an optional parameter for FileUploadOptions allowing to pass Basic Authentication credentials. Combined with HTTPS, Basic Authentication can introduce minimal security when upload files.

        Activity

        Hide
        Shazron Abdullah added a comment -

        Should be pretty straightforward, how to do it is demonstrated here:
        http://www.chrisumbel.com/article/basic_authentication_iphone_cocoa_touch

        We already include a Base64 library, so the feature should be trivial.

        Show
        Shazron Abdullah added a comment - Should be pretty straightforward, how to do it is demonstrated here: http://www.chrisumbel.com/article/basic_authentication_iphone_cocoa_touch We already include a Base64 library, so the feature should be trivial.
        Hide
        Shazron Abdullah added a comment -

        Scratch that - below is the superior solution, using NSURLCredential in a delegate method, and allows for future auth methods:
        http://stackoverflow.com/questions/1973325/nsurlconnection-and-basic-http-authentication/6814193#6814193

        Show
        Shazron Abdullah added a comment - Scratch that - below is the superior solution, using NSURLCredential in a delegate method, and allows for future auth methods: http://stackoverflow.com/questions/1973325/nsurlconnection-and-basic-http-authentication/6814193#6814193
        Hide
        Shazron Abdullah added a comment -

        All platform discussion needed.

        Show
        Shazron Abdullah added a comment - All platform discussion needed.
        Hide
        Shazron Abdullah added a comment -

        Rather than handle a new property for FileUploadOptions:http://docs.phonegap.com/en/2.5.0/cordova_file_file.md.html#FileUploadOptions

        , I would transparently handle this through the URL itself. So if a username and password pair are in the URL like so:

        http://myusername:mypassword@myserver.com/?foo=bar

        I would save the credentials, then when I get a HTTP Basic Auth challenge, use those creds.

        We could use this for FileTransfer download transparently as well.

        Show
        Shazron Abdullah added a comment - Rather than handle a new property for FileUploadOptions: http://docs.phonegap.com/en/2.5.0/cordova_file_file.md.html#FileUploadOptions , I would transparently handle this through the URL itself. So if a username and password pair are in the URL like so: http://myusername:mypassword@myserver.com/?foo=bar I would save the credentials, then when I get a HTTP Basic Auth challenge, use those creds. We could use this for FileTransfer download transparently as well.
        Hide
        Andrew Grieve added a comment -

        Might get tricky if their password has a : or @ in it.

        Show
        Andrew Grieve added a comment - Might get tricky if their password has a : or @ in it.
        Hide
        Jesse MacFadyen added a comment -

        Tricky, but that is just an implementation detail.
        http://en.wikipedia.org/wiki/Basic_access_authentication

        Could a developer not just use the header which I think is already supported.
        i.e.
        Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

        Show
        Jesse MacFadyen added a comment - Tricky, but that is just an implementation detail. http://en.wikipedia.org/wiki/Basic_access_authentication Could a developer not just use the header which I think is already supported. i.e. Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
        Hide
        Shazron Abdullah added a comment -

        Andrew Grieve I believe NSURL will encode this from string, not sure (in any case when the URL is passed through the bridge it's verbatim)

        Jesse MacFadyen yup, that is the method mentioned in the link in my first comment. I suppose I could detect the user:pass and just create the appropriate header (since we have a base64 lib in native). We could do this in JavaScript automatically but I don't think Cordova includes a js base64 function. As API implementors I'd rather provide them an easier path as provided by the URL spec

        Show
        Shazron Abdullah added a comment - Andrew Grieve I believe NSURL will encode this from string, not sure (in any case when the URL is passed through the bridge it's verbatim) Jesse MacFadyen yup, that is the method mentioned in the link in my first comment. I suppose I could detect the user:pass and just create the appropriate header (since we have a base64 lib in native). We could do this in JavaScript automatically but I don't think Cordova includes a js base64 function. As API implementors I'd rather provide them an easier path as provided by the URL spec
        Hide
        Shazron Abdullah added a comment -

        Anyways, I attached what my patch would be, it's unobtrusive

        Show
        Shazron Abdullah added a comment - Anyways, I attached what my patch would be, it's unobtrusive
        Hide
        Shazron Abdullah added a comment -

        Just realized my patch would work for upload, not download (I would have to differentiate based on self.direction) but you get the basic logic

        Show
        Shazron Abdullah added a comment - Just realized my patch would work for upload, not download (I would have to differentiate based on self.direction) but you get the basic logic
        Hide
        Andrew Grieve added a comment -

        ah, okay. So if their user/pass has symbols in it, they should encodeURIComponent on it.

        JS has base64: atob()

        With your patch, it may mean that there is an extra back-and-forth that happens? ie - if we detect the username & password before sending the initial request, we might save a round trip.

        The wikipedia article suggests that servers should understand the username & password if it exists in the URL. Are you sure your code even gets run (the server rejects the initial request) when the creds are in the url?

        Show
        Andrew Grieve added a comment - ah, okay. So if their user/pass has symbols in it, they should encodeURIComponent on it. JS has base64: atob() With your patch, it may mean that there is an extra back-and-forth that happens? ie - if we detect the username & password before sending the initial request, we might save a round trip. The wikipedia article suggests that servers should understand the username & password if it exists in the URL. Are you sure your code even gets run (the server rejects the initial request) when the creds are in the url?
        Hide
        Shazron Abdullah added a comment -

        Heh I did not know about that JS function. Not sure if it has broad support everywhere though, but that's easy to test. In this case we would use btoa: https://developer.mozilla.org/en-US/docs/DOM/window.btoa

        I'd rather we add this to cordova-js for this feature then, since I think all platforms have the header support.

        Yup, it will require that extra request for my method. My proposed patch was a quick and dirty code insertion without having to muck about with any other working parts - tradeoff is the extra request.

        When I tested it, no - the creds in the URL are not read by the server, but who knows it might just have been the server I was testing with.

        Show
        Shazron Abdullah added a comment - Heh I did not know about that JS function. Not sure if it has broad support everywhere though, but that's easy to test. In this case we would use btoa: https://developer.mozilla.org/en-US/docs/DOM/window.btoa I'd rather we add this to cordova-js for this feature then, since I think all platforms have the header support. Yup, it will require that extra request for my method. My proposed patch was a quick and dirty code insertion without having to muck about with any other working parts - tradeoff is the extra request. When I tested it, no - the creds in the URL are not read by the server, but who knows it might just have been the server I was testing with.
        Hide
        Shazron Abdullah added a comment -

        Ok, this is what I'm going to do. I'll add this to cordova-js. Some platforms that don't support window.btoa (like WP7) won't get this feature of course.

        Example code (the gist of it):

        var target = "http://username:password@www.example.com/some/path?name=value#anchor"
        if (window.btoa) {
        	// parse the url using the Location object
        	var url = document.createElement('a');
        	url.href = target;
        
        	// check whether there are the username:password credentials in the url
        	var credentials = null;
        	if (url.href.indexOf(url.origin) != 0) { // credentials found
        	    var protocol = url.protocol + "//";
        	    var atIndex = url.href.indexOf("@");
        	    credentials = url.href.substring(protocol.length, atIndex);
        	}
        	
        	if (credentials) {
        	    var authHeader = "Authorization"; 
        	    var authHeaderValue = "Basic " + window.btoa(credentials);
        		
        	    // TODO: add this to the FileTransfer headers, etc
        	}
        }
        
        Show
        Shazron Abdullah added a comment - Ok, this is what I'm going to do. I'll add this to cordova-js. Some platforms that don't support window.btoa (like WP7) won't get this feature of course. Example code (the gist of it): var target = "http: //username:password@www.example.com/some/path?name=value#anchor" if (window.btoa) { // parse the url using the Location object var url = document.createElement('a'); url.href = target; // check whether there are the username:password credentials in the url var credentials = null ; if (url.href.indexOf(url.origin) != 0) { // credentials found var protocol = url.protocol + " //" ; var atIndex = url.href.indexOf( "@" ); credentials = url.href.substring(protocol.length, atIndex); } if (credentials) { var authHeader = "Authorization" ; var authHeaderValue = "Basic " + window.btoa(credentials); // TODO: add this to the FileTransfer headers, etc } }
        Hide
        Andrew Grieve added a comment -

        Whoa! Didn't know that the anchor tag had the same properties as Location. That's neat!

        I don't think there's great support for location.origin, but location.host should work here as well, right?

        Show
        Andrew Grieve added a comment - Whoa! Didn't know that the anchor tag had the same properties as Location. That's neat! I don't think there's great support for location.origin, but location.host should work here as well, right?
        Hide
        Shazron Abdullah added a comment -

        Hard to find info about location.origin support, but it seems that (location.origin = location.protocol + "//" + location.host), so that's easy to support.

        Show
        Shazron Abdullah added a comment - Hard to find info about location.origin support, but it seems that (location.origin = location.protocol + "//" + location.host), so that's easy to support.
        Hide
        Shazron Abdullah added a comment -

        Note that this issue is about FileTransfer upload. FileTransfer download has no options to add headers, so it will continue to not have support (unless added natively).

        Show
        Shazron Abdullah added a comment - Note that this issue is about FileTransfer upload. FileTransfer download has no options to add headers, so it will continue to not have support (unless added natively).
        Hide
        Shazron Abdullah added a comment -
        Show
        Shazron Abdullah added a comment - Right now this is in my branch, un-tested: https://github.com/shazron/cordova-js/commit/18ad146a4ec3411bbf944bcdb99e067456ba6cb3
        Hide
        Andrew Grieve added a comment -

        FileTransfer just got download headers thanks to devgeeks (CB-861)

        Commit looks good

        Show
        Andrew Grieve added a comment - FileTransfer just got download headers thanks to devgeeks ( CB-861 ) Commit looks good
        Hide
        Andrew Grieve added a comment -

        Except! - should use 4 space indents

        Show
        Andrew Grieve added a comment - Except! - should use 4 space indents
        Hide
        Shazron Abdullah added a comment -

        Oops! My work machine was rebuilt recently and I forgot to add the commit hook
        I'll take a look at CB-861 and download support as well...

        Show
        Shazron Abdullah added a comment - Oops! My work machine was rebuilt recently and I forgot to add the commit hook I'll take a look at CB-861 and download support as well...
        Hide
        Shazron Abdullah added a comment -

        Fix commit - https://git-wip-us.apache.org/repos/asf?p=cordova-js.git;a=commit;h=598bbdff

        Tested download and upload using a modified node.js script (to require basic auth) from CB-2729

        Show
        Shazron Abdullah added a comment - Fix commit - https://git-wip-us.apache.org/repos/asf?p=cordova-js.git;a=commit;h=598bbdff Tested download and upload using a modified node.js script (to require basic auth) from CB-2729

          People

          • Assignee:
            Shazron Abdullah
            Reporter:
            Shazron Abdullah
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development