phpbg / easysync

Synchronize your android phone/tablet with your DAV server, the easy way.
MIT License
105 stars 6 forks source link

Feature request: Web auth #27

Open Jipok opened 9 months ago

Jipok commented 9 months ago

I tried many different self-hosted applications and over time I came to the idea that passwords are very inconvenient and unsafe. Fortunately, it turned out that various popular reverse proxies(together with authorizing middleware) transmit the Remote-User header(Sometimes X-Forwarded-User). And some applications(example: grist) can be configured for this authentication method. Even more can be configured for public access(i.e. disabling authentication) and work perfectly behind authorizing reverse proxies. Over time, I wrote a minimalistic and convenient(for me) authorizing reverse proxy Jauth. Hosting various applications has become very convenient and safe. Overall, I don't remember encountering any problems during normal use.

However, some services offer the use of their applications. And this is where the problems begin, since they use some kind of http basic auth and do not connect with any authorizing reverse proxy at all. I was thinking how to fix this. There seems to be no common way to interact between an authorizing proxy and a client(not a browser). I thought about it and decided that no special method was needed. After all, there are applications on the phone that open the browser for OAuth so that the user can log in, and then return to the application. Therefore, I added sending the WWW-Authenticate: Bearer realm="JAuth" header to Jauth. And answering with 401 code. It seems that browsers normally perceive this and display everything correctly. And mobile applications can, based on this header, understand that the user needs to display the page via WebView. I'm not an Android developer, but it seems that such a change is not difficult and does not bloat project. I decided to try to write to you to find out your opinion. Your application is one of the options that I am considering for simple and convenient synchronization of my phone with self-hosted services with WebDav support.

For your convenience, I hosted a simple webdav server https://j.ateam.undo.it/public/ and gave you access(over ssh) using https://github.com/phpbg.keys. You can go in and try it from a browser. If it also works through your application, then this will be a big step forward in the distribution of convenient passwordless access. If you are interested, I can also give access via telegram. For this I need a username or id.

P.S. I did not read the authorization standards(rfc6750, rfc2617, scheme) and therefore could have done something incorrectly. Open for discussion.

phpbg commented 9 months ago

I think it is not very difficult to intercept a 401 with a www-authenticate header, but then i don't where to redirect (which url?), and how to get the token from the browser back to the app...

If there is enough demand maybe we can dig deeper...

Jipok commented 9 months ago

but then i don't where to redirect (which url?)

Jauth simply sees that you do not have a token(or an incorrect one) and shows the authorization page(with code 401). After successful authentication, js script will update the page and the request will pass through jauth. Further, as I understand it, any webdav server willl answer you with code 200. Or another, well, obviously not 401 with WWW-Authenticate: Bearer.... You can offer your options and I can implement it.

and how to get the token from the browser back to the app

Well, I have very little experience in Android development. I asked to chatgpt and he suggested this code, which looks like a working option:

```java import android.content.Context; import android.graphics.Bitmap; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.webkit.WebChromeClient; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; public class MyWebViewActivity extends AppCompatActivity { private WebView webView; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_webview); webView = findViewById(R.id.webView); // Enable JavaScript WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); // Set WebViewClient to handle page loading and custom behavior webView.setWebViewClient(new WebViewClient() { // Store cookies if the response is not 401 or header is not "WWW-Authenticate: Bearer" private boolean shouldStoreCookies = true; @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); // Reset the flag when a new page starts loading shouldStoreCookies = true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // Check if the response is 401 or the header is "WWW-Authenticate: Bearer" WebResourceResponse response = view.getLastWebResourceResponse(); if (response != null && response.getStatusCode() == 401 && response.getResponseHeaders().containsKey("WWW-Authenticate") && response.getResponseHeaders().get("WWW-Authenticate").equals("Bearer")) { // Don't store cookies if the response is 401 or the header is "WWW-Authenticate: Bearer" shouldStoreCookies = false; } if (shouldStoreCookies) { // Retrieve cookies from the WebView String cookies = CookieManager.getInstance().getCookie(url); // Process the cookies (e.g., save them for future use) } } }); // Load the URL in the WebView String url = "https://example.com"; webView.loadUrl(url); } } ```
Jipok commented 9 months ago

Now it seems to me that it is not correct to use the header with Bearer. As I understand it, webdav servers indicate Basic or Digest. So the proxy can not send this header at all(just 401), or come up with its own name.

Jipok commented 9 months ago

@phpbg Since the webview implementation may not be desirable, can you at least add following redirects and saving cookies? Then I can just paste the session link into the application and everything will work fine. Link looks like this:

![изображение](https://github.com/phpbg/easysync/assets/25588359/4567e5f8-4eac-467e-8f80-98ab177f5953)