owncloud / core

:cloud: ownCloud web server core (Files, DAV, etc.)
https://owncloud.com
GNU Affero General Public License v3.0
8.36k stars 2.06k forks source link

Browser-based client login #24794

Closed ChristophWurst closed 7 years ago

ChristophWurst commented 8 years ago

Overview

With some identity providers (e.g. shibboleth SSO), the user logs in on an external web page which on success authenticates the user for ownCloud. As the client needs a browser window for that and desktop clients are planning to remove those (see https://github.com/owncloud/client/issues/4798), we need to find a generic way to authenticate clients on external services and create a device token if the authentication succeeds. Instead of a built-in browser an external one should be used.

Basic workflow

Step 1. Determine auth mechanism

If basic auth is used -> send HTTP header 'Authentication: basic username:password' If token auth is used -> send HTTP header 'Authentication: basic username:token' or 'Authentication: token xxx' if #24763 was implemented.

Step 2. Request login URL + temporary token

Note: the URL must contain the temporary token, so that the identity provider redirects the user back after successful login (or if the user was already logged in).

Step 3a. Open browser window for user and let her/him authenticate

Step 3b. Polling the auth state from the server

Step 4. Use the token

This will also allow to connect sync clients to accounts which are two-factor enforced. There we can use ownCloud itself as 'identity provider' and let the user solve the 2FA challenge. We could even go one step further and do the login purely in a browser, even if no 2FA or special identity provider is used. This would be an interesting login mechanism for untrustworthy clients you don't want to enter your password.

HTTP workflow

Requesting auth mechanisms/providers: C -> S GET owncloud/auth/test C <- S 401 (+ list of providers) C -> S POST owncloud/auth/provider (+ provider id?) C <- S 200 URL + temp token

Login in external browser: C -> ID GET identityprovider/login C <- ID 200 login form C -> ID POST idendityprovider/login C <- ID 302/303 owncloud/auth/auth/finish

Meanwhile, polling the server: C -> S GET owncloud/auth/status?token=xxx C <- C 200 status, either 'pending' or 'finished' + new device token

Issues

ref https://github.com/owncloud/client/issues/4798

cc @danimo @PVince81 @DeepDiver1975 @MTRichards @butonic @LukasReschke @owncloud/desktop-developers @owncloud/android-developers @owncloud/ios-developers

PVince81 commented 8 years ago

I think the client doesn't need to know about how the web UI logs itself in, it doesn't interest the client.

Basically there are only two authentication methods:

In the case of browser login, the client connects to the server and the server returns a constant URL, for example "https://host/owncloud/loginsuccess". This page itself requires log in, so opening it as an unauthenticated user will automatically trigger the existing authentication mechanism (SSO, 2-factor, whichever). This already exists and doesn't need additional work and doesn't require the client to know that there's SSO or 2-factor. Then, as soon as the user is authorized to open the "loginsucess" page, that page internally creates the real auth token and makes it available through the polling endpoint.

In some cases, the user already has an authenticated browser of the same type, so opening the URL "loginsuccess" will directly generate the token without requiring additional login.

rullzer commented 8 years ago

I would even go a step further and force clients to use the weblogin method. That way only tokens are used to secure our users. And since it is all async without real user involement those tokens can be huge by default :)

Now of course the client will need to support basic auth for quite some time still (since we support older servers). But a simple check against status.php could disable basic auth by definition.

We want users to use tokens by default so don't give them a choice ;)

guruz commented 8 years ago

@rullzer In general I agree, but then how can people easily use curl, davfs, file managers etc?

ChristophWurst commented 8 years ago

@guruz you can use the generated token as password, so basic auth user:token works.

rullzer commented 8 years ago

Exactly they have to generate device tokens on the webinterface...

ChristophWurst commented 8 years ago

This seems to be the workflow we aim for: https://en.wikipedia.org/wiki/OAuth#OpenID_vs._pseudo-authentication_using_OAuth

rperezb commented 8 years ago

@davivel your input is appreciated here

ChristophWurst commented 8 years ago

Authentication mechanism detection

With multiple authentication mechanisms available, clients need to know which one is used to either prompt for for login credentials or open an URL in an external browser.

Auth

These are the auth mechanisms we support:

Token generation

These are the token generation mechanisms we support:

Possible setups/configuration

These are the setups that we need to support:

Client detection

We need to find a way for clients to detect which auth mechanisms and token generation mechanisms are supported. As discussed with @PVince81 we think that a special info route could be used to return that info. E.g. the client sends a request to /auth/info and gets a list of auth mechanisms and/or token generation mechanisms it can choose from. That route must be accessible without user credentials.

ChristophWurst commented 8 years ago

@danimo @davivel @PVince81 @DeepDiver1975 ^

davivel commented 8 years ago

Thinking in mobile (Android biased):

Step 3a. Open browser window for user and let her/him authenticate

That means OC app goes to background. Easy.

Step 3b. Polling the auth state from the server

Polling in mobile is not generally a good idea, but this is supposed to finish soon, so we could leave an async job or a service in background polling the endpoint for a limited time. It detects the log-in is completed. And then, what we do?

The user just logged into ownCloud, and expects the next window to appear is in the ownCloud app.

Options:

Of course, my favorite option is 3, since minimizes the changes needed in the mobile apps. I also like 4, but I don't know if would work fine in desktop (though Safari does it with iTunes).

ChristophWurst commented 8 years ago

@davivel thanks for your input. Personally, I think that option 3 would work best as you have full control over the browser window. Especially closing it as soon as you detect the successful login process is finished will enhance the UX. See https://github.com/owncloud/core/pull/24835#issuecomment-221549525 for a detailed test of what is already possible with my PR. Would 4. be necessary at all if the polling tells you whether the login process was finished or not? Seems redundant.

davivel commented 8 years ago

Would 4. be necessary at all if the polling tells you whether the login process was finished or not? Seems redundant.

No, it's designed specifically so that we don't need to poll. It's intent is being an alternative to implement the polling.

But polling is not needed either in alternative 3, and you wouldn't have to change step 3a.

ChristophWurst commented 8 years ago

Okay, makes sense. However, that would be specific to mobile. That means we'd have to provide two different redirect URLs depending on the client platform.

davivel commented 8 years ago

About the authentication mechanism detection, using a specific path to get the list is OK to me, though I'm not sure from your description what would be the list of responses. The setups with 2FA enabled or disabled include the same combinations in https://github.com/owncloud/core/issues/24794#issuecomment-222933509, how will the client distinguish one setup of other?

Related to authentication detection: what will the server respond to a non-authenticated request on a DAV resource? A 401 response must include an authentication challenge, what would be the content of this if the server does not allow basic authentication?

davivel commented 8 years ago

how will the client distinguish one setup of other?

Self-respond, I guess that should be transparent for the client.

So, the response to GET /auth/info should be a list of valid combinations of authX + tokenY, right?

ChristophWurst commented 8 years ago

@davivel exactly

ChristophWurst commented 8 years ago

Related to authentication detection: what will the server respond to a non-authenticated request on a DAV resource? A 401 response must include an authentication challenge, what would be the content of this if the server does not allow basic authentication?

We need to find a solution for that, too. The fact that we support two different types of basic auth (password or token) might complicate this.

davivel commented 8 years ago

I guess that basic auth with password should keep the "Basic" word for itself, and we should define a specific value for basic with token.

I relate this to auth detection because that's what we do now to find out the auth method, make an unauthenticated request to the root folder and check the response. What makes me think in Shibboleth: the plan is integrating it with Auth3?

ChristophWurst commented 8 years ago

@davivel that is not yet possible, see https://github.com/owncloud/core/issues/24763

davivel commented 8 years ago

Seen, I guess that differentiate it is against the intention of using it as a transparent legacy solution.

Any thought about my other question? Is the plan integrate Shibboleth in Auth3? Right now the detection of Shibboleth as the method to authenticate is based in catching a 302 response with certain keywords when accessing the root folder with an unauthenticated request. If we don't integrate Shibboleth in the scheme of available auth methods, we'll need different detection paths in the client side.

ChristophWurst commented 8 years ago

Yes, the plan is to use the async client login process for shibboleth, where the user logs in on an external browser and the client gets a new token after the successful login process. https://github.com/owncloud/core/pull/24835#issuecomment-221597494 does exactly that, but was postponed to 9.2.

At least how I understood it, Client auth detection should replace that redirect/shib detection clients currently do.

PVince81 commented 7 years ago

I think this is obsoleted by OAuth2 ?

michaelstingl commented 7 years ago

I think this is obsoleted by OAuth2 ?

@butonic @pmaier1 Could you help here?

butonic commented 7 years ago

yes

DeepDiver1975 commented 7 years ago

why close?

DeepDiver1975 commented 7 years ago

A PR was started on this - https://github.com/owncloud/core/pull/26742

PVince81 commented 7 years ago

that PR was merged, what's left ?

PVince81 commented 7 years ago

likely still a lot to do.

pmaier1 commented 7 years ago

As soon as we have oAuth2 ready on server- and client-side clients should just use oAuth2 and should not have to tamper with anything else anymore.

PVince81 commented 7 years ago

obsolete ?

lock[bot] commented 5 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.