bugdavfs2 - Bugs: bug #57589, Add WebDAV OAuth token...

 
 

bug #57589: Add WebDAV OAuth token authorization method to davfs2

Submitter:  Alexey Murz Korepov <murz>
Submitted:  Mon 13 Jan 2020 07:36:40 AM UTC
   
 
Category:  None Severity:  3 - Normal
Item Group:  None Status:  Wont Fix
Privacy:  Public Assigned to:  _71007
Open/Closed:  Open
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Wed 27 Oct 2021 11:59:18 PM UTC, comment #11: 

Hi Werner,

I have a need to use tokens, similar to what Alexey and Diogo describe.

I was able to make it work like this:

1. Set `add_header Authorization "Bearer <token>"` in davfs2.conf
2. Mount the volume
3. Sometime later when the token changes, edit davfs2.conf, unmount, and then re-mount the volume

An external program can check for new tokens and automate these steps.

It's also possible to do this with a per-server configuration. As you mentioned, the manual contains this gem:

> The file may contain sections that are for one specific mount point only. Such a section starts with a line, that contains the full path of the mount point enclosed in square brackets. The section ends at the start of the next section or the end of file. Options that shall apply to all mounted file system must come before the first sections. Options given in a mount specific section will have precedence.


So if webdav.example1.com is mounted at `/mnt/volume1`, and webdav.example2.com is mounted at `/mnt/volume2`, they can each have a different authorization token with this configuration:


[/mnt/volume1]
ask_auth 0
add_header Authorization "Bearer token1"

[/mnt/volume2]
ask_auth 0
add_header Authorization "Bearer token2"


Just thought I'd mention this here for anyone else reading this thread, because I missed the significance of that paragraph in the manual the first time I read it.

Thanks,
Jonathan

Jonathan Buhacoff <xalqor>
Tue 09 Mar 2021 10:32:51 PM UTC, comment #10: 

Hey, thanks for getting back.

1) Ok, so maybe we could push this change there? To be seen.

2) You are storing a plaintext password on a local file, this is what I say should be avoided. But then you can also say that I might store a token in a file (although they are short lived and limited in scope). But fine, it's not much better...

3) you usually have an access token and a refresh token. The access is the one that is used and should be valid for some minutes. You use the refresh to.. refresh and get 2 new tokens. This last token can be requested to have a longer time (it's called offline access), but even then it should have an expiration time.

4) What I was saying is that, just like the user/pass combo, maybe we can assume that they exist and got created by someone. In our case, we already have an application that refreshes and stores the valid token in a file. To send it, as it was mentioned, we just need to set the header with the token we got.

5) Ofc we could do the refresh from davfs, but as in point 4) we can assume it's being updated outside of davfs. This first iteration would make the implementation in davfs simple and still allow these integrations by delegating that task.

And I'm not seeing any problem. I already have an app that gets tokens updated and stores them in files. I mentioned before that there are many libraries that can be used to read the token and see its expiration (you can decode it). If you know the expiration, you know when this token is invalid, therefore you do not need to read the file every-time you do a request.. Only when it's invalid.

Ofc the token might've been revoked, or maybe you read the file again and you realize that it's still expired. But so can a password be revoked... I don't see why wouldn't davfs behave exactly the same in both cases.

If you want, I can explain our use case in more detail. We might even find someone willing to contribute this change to the code (we're loooking). But I would prefer to know beforehand wether you're going to be against it by principle or open to the proposal.

Cheers,
Diogo

Diogo Castro <diogo>
Tue 09 Mar 2021 05:46:45 PM UTC, comment #9: 

1)
Authentication is done by the Neon library. davfs2 only passes the credentials to the library.

2)
"having plain text passwords is something that nobody should do in this day and age"
You are using TLS anyway. There is no plaintext password.

3)
"since tokens might be short(ish) lived". Well, Alexey says: "The token is not changed frequently, it is static"

4)
'This webdav client doesn't do authentication, it just needs to send the standard authorization header with the token that it got from "someone/somewhere"'
Where is "someone/somewhere"? The problem is how to get the token and not how to send it.

5)
"But I would suggest it  tried to read the secrets file once more, as it might have been updated already with a newer one"
Who is by what kind of magic updating which mysterious secrets file?

Just write an application that always stores the correct token in some well-known file and additionally tell me, how davfs2 gets informed about changes (without reading the file for every request). In this case it might be usefull to talk again.

Werner

- <_71007>
Tue 09 Feb 2021 10:03:11 AM UTC, comment #8: 

Hi,

As Alexey mentioned, oAuth is the way every cloud provider is moving precisely because it allows the use of different tokens for different services, they have shorter life than a password (so stealing them is not usually a major problem), you can do delegation, etc, etc. Some have removed the basic auth altogether and many others are considering the same (having plain text passwords is something that nobody should do in this day and age).

While the protocol might be harder to implement and there might be other considerations about it, I don't see what that has to do with this dav client... These problems are for the services that need to implement the authentication flow. This webdav client doesn't do authentication, it just needs to send the standard authorization header with the token that it got from "someone/somewhere" (and there is no "implementation for different commercial services", they need to accept "Authorization: Bearer xxx").

The only problem, since tokens might be short(ish) lived, is that we might need to update them. Again, this webdav client doesn't need to do anything special. One possibility is that it just fails. But I would suggest it  tried to read the secrets file once more, as it might have been updated already with a newer one, and doing the call again before failing. An optimization would be to read the token to check its expiration to avoid a round trip (there are a couple of libraries that can be used: https://jwt.io/).

Do you think this could be done?
Diogo

Diogo Castro <diogo>
Thu 16 Jan 2020 03:37:11 PM UTC, comment #7: 

"How can I configure davfs2 to not send Basic auth header ..."
davfs2 only uses this header when requested by the server. In this case davfs2 got a 401-response from the server. Obviosly your authorization header did not work.

"Also in davfs2.conf I can set only global value for all hosts, not per-host, like in ~/.davfs2/secrets file."
What about "Read That Fine Manual"?
Of course you could if only you would read the manual. Maybe that is also the reason why your header file does not work.

After all you heard about the debug option. With "debug http" you can check wether your header line is send as you expected.

"Can you ask Google to provide different passwords for each service in your personal account?"
You think I am not as powerful as Google or Yandex? This might be an error. I can ignore your requests just as well.
It is ridiculous when people ar asking developers of free sofware to change their software, but don't ask companies that earn a lot of money with their software. The problem is Yandex and their strange kind of Basic authentication, not davfs2.

Werner

- <_71007>
Thu 16 Jan 2020 11:28:35 AM UTC, comment #6: 


>  I already did - a long time ago. With option "add_header" you can add any header you want, e.g. your non-standard authorization header. Details are in "man davfs2.conf".


Thanks for info, this is exactly that I want for customize connection auth string! Before I search this in secrets file documentation only.

I try this, and if I fill 'add_header' option, davfs2 seems still add "Basic" header line (even with empty secrets file and ask_auth=0) when talking with webdav server, so connection to Yandex fails with error:

mount.davfs[2970]: davfs2 1.5.5
 mount.davfs[2970]: Initializing webdav
 mount.davfs[2970]: ah_create, for WWW-Authenticate
 mount.davfs[2970]: ah_post_send (#0), code is 401 (want 401), WWW-Authenticate is Basic realm="Yandex.Disk"
 mount.davfs[2970]: auth: Got challenge (code 401).
 mount.davfs[2970]: auth: Got 'Basic' challenge.
 mount.davfs[2970]: auth: Trying Basic challenge...
 mount.davfs[2970]: auth: Accepted Basic challenge.
 mount.davfs[2970]: auth: Sending 'Basic' response.
 mount.davfs[2970]: ah_post_send (#1), code is 401 (want 401), WWW-Authenticate is Basic realm="Yandex.Disk"
 mount.davfs[2970]: auth: Got challenge (code 401).
 mount.davfs[2970]: auth: Got 'Basic' challenge.
 mount.davfs[2970]: auth: Trying Basic challenge...
 mount.davfs[2970]: authentication failure:
 mount.davfs[2970]:   Yandex.Disk
 mount.davfs[2970]: auth: No challenges accepted.
Could not authenticate to server: rejected Basic challenge


How can I configure davfs2 to not send Basic auth header, and use only strings from 'add_header'?

Also in davfs2.conf I can set only global value for all hosts, not per-host, like in ~/.davfs2/secrets file.

So can you please add similar feature to ~/.davfs2/secrets file? Thanks!


P.S. I have found description of Yandex WebDAV connection in English here: https://tech.yandex.com/disk/webdav/




> Your provider allows different OAuth-tokens for different services but does not allow different passwords for different services. That is voluntary nonsense. You should ask your provider to change this and just comply to the standards.


Can you ask Google to provide different passwords for each service in your personal account? One password for GMail, second for Google Docs, third for Google Calendar, etc? No, google suggest use personal tokens for each service to, like most of other providers!


Alexey Murz Korepov <murz>
Thu 16 Jan 2020 10:50:31 AM UTC, comment #5: 

"So, if provided way is hard to implement, can you please provide any other way for customization of Authorization header line text in davfs2? Thanks!"
I already did - a long time ago. With option "add_header" you can add any header you want, e.g. your non-standard authorization header. Details are in "man davfs2.conf".

Additional advise:

  • Remove all file permission for group and others from file davfs2.conf, so nobody but you can read your token.
  • Your header-value probably contains spaces. You must enclose the value in double quotes.
  • Additionaly set option "ask_auth 0" to prevent useless input requests.


Some remarks about the authentication methods used by your provider:

  • OAuth with long lasting tokens as used by your provider is nothing else but HTTP-Basic authentication with non-standard syntax. It adds no value but makes it less interoperable, just as Eran Hammer points out.
  • Your provider allows different OAuth-tokens for different services but does not allow different passwords for different services. That is voluntary nonsense. You should ask your provider to change this and just comply to the standards.


Werner

- <_71007>
Wed 15 Jan 2020 06:04:30 PM UTC, comment #4: 

So now davfs2 allow to use only hard-coded format of Authorization header string:
"Authorization: Basic [base64(login:password)]"

I ask to add any way for override this hard-coded format via custom string, filled in ~/.davfs2/secrets file.

Alexey Murz Korepov <murz>
Wed 15 Jan 2020 05:36:03 PM UTC, comment #3: 


> I have no idea how you get that frequently changing token.


The token is not changed frequently, it is static, but can be genereated unique for each service and client, instead of password, that only one for all service.

For example, I have "mycompany@yandex.com account (this is like mycompany@gmail.com) with password "myPassword123", and two ways of authorization - via passwords, and via token.

1. First way via password:

On each server I must fill in "~/.davfs2/secrets" my password in plain tex. If this password will leaked from one server, hacker will got full access to all yandex.com services (email, cloud drive, and many other). And I need to change password and update ~/.davfs2/secrets file on each server with new password.


2. Second way via token:

On yandex.com service I generate unique token for each server, and fill it in ~/.davfs2/secrets file. If this password will leaked from one server, hacker will got access only to webdav service, not for any other (email, cloud drive, etc)! Also I can quickly invalidate this unique token for this server, and all other servers will continue work using they unique tokens.


> it is common practice to use a SSL/TLS-connection when transfering credentials.


SSL/TLS-connection already used, the problem is that my general password is stored unencrypted in ~/.davfs2/secrets file!


> And finally it is highly extensible and you probably would have to write different code for every comercial server. I will not engage in this.


My feature request is only to allow filling custom text to "Authorization" header line text via secrets file, not to extend davfs2 for each commercial server individually.

If you implement this feature in davfs2, users will can write his own customizations, even periodically rewrite ~/.davfs2/secrets file via external script to add dynamic tokens support.

So, if provided way is hard to implement, can you please provide any other way for customization of Authorization header line text in davfs2? Thanks!

Alexey Murz Korepov <murz>
Wed 15 Jan 2020 05:12:06 PM UTC, comment #2: 

I don't speak russian and I have no idea how you get that frequently changing token. More generally:

From RFC 6749:
"The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, ..."

It has nothing to do with how the owner(s) of the resource access the resource. I can't see why this token would be in any way more secure than a password. By the way: for almost a quarter of a century it is common practice to use a SSL/TLS-connection when transfering credentials.

Additionally: OAuth comes in two RFC's (6749 and 6750) with 75 and  17 pages. Wikipedia writes (https://en.wikipedia.org/wiki/OAuth#Controversy):
"Eran Hammer resigned from his role of lead author for the OAuth 2.0 project, ...
...
In comparing OAuth 2.0 with OAuth 1.0, Hammer points out that it has become 'more complex, less interoperable, less useful, more incomplete, and most importantly, less secure.'"

And finally it is highly extensible and you probably would have to write different code for every comercial server. I will not engage in this.

Werner

- <_71007>
Mon 13 Jan 2020 12:34:52 PM UTC, comment #1: 

As example of WebDav auth with Yandex OAuth token implementation, we can lookup rclone Yandex module, here is documentation: https://rclone.org/yandex/

Alexey Murz Korepov <murz>
Mon 13 Jan 2020 07:36:40 AM UTC, original submission:  

Many WebDAV cloud providers disabling default basic plain text auth by security reasons, and use tokens for authorization.

For example, here https://yandex.ru/dev/disk/doc/dg/concepts/quickstart-docpage/ is described Yandex OAuth token authorization method (in Russian). With basic auth Yandex.Disk WebDAV works very bad because of manual traffic limits and forced connection drops on server side :(

Seems davfs2 now support only Basic Auth, described ad https://tools.ietf.org/html/rfc2617 - yes?

Can you please add custom token authorization method to davfs2?

Seems this is not so hard, we only need to change "Authorization" header line from:
"Authorization: Basic [base64(login:password)]"
to
"Authorization: OAuth [token string]"

In ~/.davfs2/secrets file this can be represented as:
https://webdav.example/path "[full authorization header line text]"

Example:
https://webdav.yandex.ru/ "OAuth 0c4181a7c2cf4521964a72ff57a34a07"

What do you think about this idea? Thanks!

Alexey Murz Korepov <murz>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by xalqor (Posted a comment)
  • -email is unavailable- added by diogo (Posted a comment)
  • -email is unavailable- added by _71007 (Posted a comment)
  • -email is unavailable- added by murz (Submitted the item)
  • -email is unavailable- added by murz
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follow 3 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2020-01-15 _71007 StatusNone Wont Fix
        Assigned toNone _71007
    2020-01-13 murz Carbon-Copy- Added murz

    Back to the top

    Powered by Savane 3.13-3230.
    Corresponding source code