Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAuth 2.0 support for ownCloud [$5] #10400

Closed
11 tasks
LukasReschke opened this issue Aug 13, 2014 · 23 comments
Closed
11 tasks

OAuth 2.0 support for ownCloud [$5] #10400

LukasReschke opened this issue Aug 13, 2014 · 23 comments

Comments

@LukasReschke
Copy link
Member

LukasReschke commented Aug 13, 2014

OAuth 2.0 support is a key requirement if we want to start make ownCloud attractive as a platform for third-party developers. (e.g. if we want that they integrate ownCloud into their application)

Basically, OAuth is a protocol that allows third-party applications to request access to protected informations without providing the password to another party.
Currently, third-party applications have to use Basic Authentication (that is sending the username and the password) to access the ownCloud instance which has the following disadvantages:

  • Users have to provide their credentials to third-party applications. If one of the third-party providers has been compromised the ownCloud login will be lost.
  • An authentication can only be "revoked" by changing the user password which is suboptimal.
  • Third-Party developers do currently have access to the whole ownCloud instance, they even could change your password.

Instead of using passwords for authorization OAuth is using unique tokens for every client. In OAuth, the client requests access to the needed resources (scopes) by redirecting the user to a website where he has to approve these permissions.

For example, a user might grant a "mobile news" application only access to the "news" API. Instead of entering his own credentials into the application the user just has to approve authorize the application via the ownCloud web interface.

User stories

  1. As a user, I want to be able to grant third-party applications access to my data without providing them my password or granting access to the whole instance.
  2. As a user and administrator, I want to see which applications have access to which data and manage them.
  3. As a developer, I want to use standard libraries to integrate with ownCloud.

Acceptance criteria

  • Server MUST verify the CSRF token in any case. A request without CSRF token MUST be logged. (this is something that we should add to the CSRF implementation directly)
  • Server MUST ensure that no session fixation is possible
  • Server MUST not leak the authorization code (e.g. due to an open redirector)
  • OAuth implementation MUST be fully audited and self-implemented. I'm tired by vulnerabilities in third-party code. This is not acceptable in such critical components.
  • Server MUST verify the client_id issued for tokens
  • Server MUST give applications the possibility to create their own permissions
  • Users MUST be able to see see all the applications that have been granted permission, their scope (including descriptive text), when they were last used
  • Users MUST be able to revoke granted permissions
  • Admins MUST be able to limit OAuth to domains or completely disable it
  • Server MUST allow self-registration of applications
  • Server SHOULD implement the defined scopes below

Scopes

core

  • core:user:read
    • Grants read access to the user's mail address and name
  • core:user:write
    • Grants write access to the user's mail address and name

files

  • files:appfolder
    • Gives application full permissions on it's own application specific folder. This appfolder will be created automatically in the users root directory
  • files:list('/path/')
    • Allows the application to list all files in the specified path.
  • files:read('/path/')
    • Allows the application to read all files in the specified path.
  • files:write('/path/')
    • Allows the application to edit or create files in the specified path.
  • files:delete('/path/')
    • Allows the application to delete files in the specified path.

files_sharing

  • files_sharing:appfolder
    • Gives application sharing permissions on it's own application specific folder.
  • files_sharing:list('/path/')
    • Gives application the possibility to list shares in this subfolder.
  • files_sharing:share('/path/')
    • Allows the application to share all files in the specified path.
  • files_sharing:unshare('/path/')
    • Allows the application to unshare all files in the specified path.

Considerations

As applications should be able to register their own scopes (e.g. "contacts:read" to allow an application to read all contacts) we need it to make it as easy as possible to define their own scopes and which permissions they do grant.

I'd propose that we add the definitions of the scopes to "appinfo.xml", since we might reuse them in future for something else than OAuth we should give them a generic name.

<scopes>
    <read>
        <description>Grants read access to files in $1</description>
    </read>
    <write>
        <description>Grants write access to files in $1</description>
    </write>
</scopes>

$1 refers in this case to the first parameter, $2 would refer to the second parameter etc. (see below for some examples)- Those values are used to explain the permissions to the end-user when granting authorization.

To define which controllers are accessible by a scope we should use the annotations of the appframework:

/**
* @NoAdminRequired
* @CORS
* @Scope('read')
*/
public function read() {}

/**
* @NoAdminRequired
* @CORS
* @Scope('write')
*/
public function write() {}

/**
* @NoAdminRequired
* @CORS
* @Scope('read', 'write') // 'read' or 'write' permission are required
*/
public function both() {}

The scopes are specific for a specific application, if the above controller would be in the "contacts" app it would use the "read" and "write" scope definition from it. If it wants to check other permissions the full scope name (prefixed with the application identifier and a :) has to be provided:

/**
* @NoAdminRequired
* @CORS
* @Scope('read', 'files:read') // 'read' from the contacts app or 'read' from the files app are required
*/
public function read() {}

To read the parameters (e.g. files:foo('/blah/', 'foo')) $this->scope->0->0 can be used. This will return the first argument of the first scope (/blah/) defined in @scope. $this->scope->0->1 would return the second parameter of the first agument (foo).

In our legacy applications which are not using the AppFramework we could use a function call as following:

\OC\User::requireScope(array('contacts:read', 'files:read'));
\OC\User::readScopeValue('contacts:read', 0); // Would read the first argument of `contacts:read`

It shall be noted that if no scope is defined no access will be granted. To allow any scope * can be used as wildcard. (@Scope('*'))

Summoning @karlitschek @MTRichards @DeepDiver1975 @Raydiation

Please:

  1. Discuss this proposal and the suggested implementation
  2. Schedule this feature. I'd really like to have this in ownCloud 8.
@LukasReschke
Copy link
Member Author

also some other folks that might be interested in this:

@PVince81 @MorrisJobke

@LukasReschke
Copy link
Member Author

The scopes might also be useful if we want to implement proper ACLs in the future ;-)

@jancborchardt
Copy link
Member

I love this! Already added it to the »Integration Efforts« section on https://github.com/owncloud/core/wiki/Apps#integration-efforts

This is especially interesting for the 3rdparty mobile and desktop apps as well. cc @davivel @phedlund @David-Development @Leandros @maltefiala

@Leandros
Copy link

Sounds amazing!

@davivel
Copy link

davivel commented Aug 13, 2014

This seems really, realy cool.

A couple of things I miss:

  • From the description I'd guess this is about supporting the authorization code grant type, and/or the implicit grant type; I think that keeping this detail documented in the proposal would be important.
  • We should define as soon as possible how will the clients discover the authorization endpoint, since this is something specifically out of the scope of the OAuth spec but completely essential for the implementation.

@LukasReschke
Copy link
Member Author

From the description I'd guess this is about supporting the authorization code grant type, and/or the implicit grant type; I think that keeping this detail documented in the proposal would be important.

I'm planning to support both.

We should define as soon as possible how will the clients discover the authorization endpoint, since this is something specifically out of the scope of the OAuth spec but completely essential for the implementation.

Yep. There are also some other important things that aren't set yet. Once we got a decision for what release this will be scheduled this I'll create a throughout documentation with examples (similar to https://developer.github.com/v3/oauth/) to make sure that the implementation will actually be used :-)
If we don't officially set this on the roadmap I'll have to implement this in my spare time which means that it may take a "little bit" ;) longer.

@tuxbox
Copy link

tuxbox commented Aug 13, 2014

This is a long-awaited addition to owncloud. Huge leap forward when this is implemented for third-party apps.

@BernhardPosselt
Copy link
Contributor

The proposal as discussed on irc is code wise too complicated for app devs. More discussion will follow at the conference :)

@PVince81
Copy link
Contributor

From what I understand, the OAuth scope only applies to public API endpoints, not internal apps, which means WebDAV, OCS Share API, etc.

I suggest to start with simple app-based scopes, combined with either "read-only" or "read-write" permissions.

The WebDAV scope could have an additional "root" parameter to specify a root (chroot) in which the app can access. This might be achievable using SabreDAV plugins.

The other APIs need a mechanism to recognize the scope and limit themselves accordingly.

@tomneedham
Copy link
Member

Idea (before I forget):

  • Each app has read and write scope for simplicity (files maybe something more complex?)
  • We add a tag to info.xml like <oauth2support>true</oauth2support>
  • Only apps with the above will be considered for requests using oauth
  • Apps with the above tag, must implement some sort of OCP\OAuth->hasRead() and hasWrite()
  • On request, we check if the user has (oauth2support) AND (read | write) scope permitted, if so we load the app
  • On AppFramework we could maybe implement some annotations for read and write scope so as to automatically return 'unauthorized' if the scope is not permitted.

@PVince81 @LukasReschke @Raydiation @MorrisJobke

@LukasReschke
Copy link
Member Author

As discussed:

  • Each app has read and write permission for simplicity

  • Additional permissions are defined in info.xml; New permissions can be created, the description of existing permissions will be overridden.

    <oauth>
    <!-- Built-in permission read will not be overridden, just the description-->
    <permission type="read">
        <descriptions>Optional descriptive text</descriptions>
    </permission>
    <!-- custom permissions can be done like this-->
    <permission type="custom">
        <descriptions>Optional descriptive text</descriptions>
    </permission>
    </oauth> 
  • Permissions can be applied to each controller method like

    <?php
    /**
     * @OAuth(read, write)
    */
    public function something()
  • Legacy apps will use something like this

    <?php
    OCP\JSON::oauth('read', 'write');

@tomneedham
Copy link
Member

👍

@Cysioland
Copy link

👍

@kriede
Copy link

kriede commented Mar 23, 2015

Would love to see this!

@owncloud owncloud locked and limited conversation to collaborators Mar 23, 2015
@PVince81 PVince81 modified the milestones: 9.0-next, 8.2-current Sep 21, 2015
@PVince81
Copy link
Contributor

We're past feature freeze, moving to 9.1

@PVince81 PVince81 modified the milestones: 9.1-next, 9.0-current Feb 12, 2016
@butonic
Copy link
Member

butonic commented Jun 30, 2016

@ChristophWurst has implemented token based auth for 9.1.

@DeepDiver1975 We should probably see if we can build upon it and evolve it into an OAuth 2.0 compatible mechanism because firewalls like BigPoint F5 are introducing support for OAuth 2.0 as well.

Moving milestone to 9.2 to research then.

@butonic butonic modified the milestones: 9.2-next, 9.1-current Jun 30, 2016
@PVince81 PVince81 removed the triage label Nov 16, 2016
@PVince81
Copy link
Contributor

First step: introduce the base work for oauth2 authentication @PhilippSchaffrath.
Goal is to first make it possible for ownCloud clients to authenticate with oauth2.

Everything else like permission scoping should be done later as a second step.

@phisch
Copy link
Contributor

phisch commented Nov 21, 2016

@PVince81 means we need acces/refresh tokens, clients and grants, i would probably need to implement scopes too but that would be an empty implementation at first.

The grants we need right now:

  • 4.3. Resource Owner Password Credentials Grant
  • 6 Refresh Token Grant
  • Custom Grant (to support authentication with shibboleth and others)

Also a simple resource server to protect apis. This might be tricky because of our different routings/controllers. I imagine we don't want to protect everything.

@DeepDiver1975
Copy link
Member

This might be tricky because of our different routings/controllers.

We shall only care about two different endpoints to pretect: webdav and our OCP\AppFrameWork\Controllers.
Anything else is considered legacy and needs to be migrated anyway.

@davivel
Copy link

davivel commented Dec 7, 2016

4.3. Resource Owner Password Credentials Grant

That will make life in clients much easier, for sure.

@davivel
Copy link

davivel commented Dec 7, 2016

Custom Grant (to support authentication with shibboleth and others)

And this is what will bring back the pain again, I guess :D

@DeepDiver1975 DeepDiver1975 changed the title OAuth 2.0 support for ownCloud OAuth 2.0 support for ownCloud [$5] Feb 7, 2017
@PVince81
Copy link
Contributor

I head there is an for that ? Link then close ?

@PVince81 PVince81 modified the milestones: triage, 10.0 Jun 29, 2017
@guruz
Copy link
Contributor

guruz commented Jun 29, 2017

@guruz guruz closed this as completed Jun 29, 2017
@felixboehm felixboehm removed this from the triage milestone Apr 10, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests