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

Custom Authentication Mechanisms for WebDAV and APIs #26742

Merged
merged 32 commits into from Mar 9, 2017
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
be3bcba
Add if-statement for switching auth backends
joneug Nov 28, 2016
e23a570
Implement determineUsername function
joneug Nov 29, 2016
45983f1
Update PHPDoc
joneug Nov 30, 2016
76a37fa
Update code for changes in OAuth 2.0 app
joneug Dec 14, 2016
14cabab
Replace own AbstractBearer implementation with that of sabre/dav
joneug Dec 18, 2016
c1833bb
Add OAuth 2.0 App as submodule
joneug Dec 23, 2016
43f12b0
Update comment in webdav.php
joneug Jan 9, 2017
38b2062
Improve if-statement for the auth backend
joneug Jan 11, 2017
b9cd079
Update code for changes in OAuth 2.0 app
joneug Jan 23, 2017
253c827
Add OAuth2Test
joneug Jan 24, 2017
3d6dc7e
Update OAuth2Test
joneug Jan 24, 2017
ae46539
Merge branch 'master' of https://github.com/owncloud/core into dav-oauth
joneug Jan 29, 2017
7f5fe29
Add OAuth 2.0 login mechanism to Session.php for use in api.php
joneug Jan 29, 2017
190ebab
Update loginWithOAuth2 function
joneug Jan 29, 2017
0962285
Update OAuth 2.0 App
joneug Jan 29, 2017
58949f6
Improve tearDown function in OAuth2Test
joneug Jan 30, 2017
bfa9c04
Refactor OAuth2Test
joneug Jan 30, 2017
1259886
Refactor OAuth2Test
joneug Jan 30, 2017
2142bb3
Remove submodule oauth2
joneug Jan 31, 2017
b511469
Update .gitignore
joneug Jan 31, 2017
fa021a3
Merge branch 'dav-oauth' into api-oauth
joneug Jan 31, 2017
99eedf0
Remove submodule oauth2
joneug Feb 2, 2017
ecbcea3
Delete OAuth2Test.php
joneug Feb 2, 2017
92af9b1
Remove reference to OAuth2 class in webdav.php
joneug Feb 14, 2017
7e0b8ae
Add plugin mechanism for authentication
joneug Feb 14, 2017
480173d
Update PHPDoc in IAuthModule
joneug Feb 14, 2017
574ce23
Update PHPDoc for auth function
joneug Feb 14, 2017
213ccd7
Merge branch 'master' of https://github.com/owncloud/core into dav-oauth
joneug Feb 23, 2017
c78e854
Add getUserPassword function in IAuthModule
joneug Mar 2, 2017
945f6bc
Add loading of additional AuthBackends for webdav interface
joneug Mar 2, 2017
cde90f6
Add type check for IAuthModule
joneug Mar 7, 2017
b378b45
Merge branch 'master' of https://github.com/owncloud/core into dav-oauth
joneug Mar 9, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions apps/dav/appinfo/v1/webdav.php
Expand Up @@ -55,5 +55,9 @@
return \OC\Files\Filesystem::getView();
});

// allow setup of additional auth backends
$event = new \OCP\SabrePluginEvent($server);
\OC::$server->getEventDispatcher()->dispatch('OCA\DAV\Connector\Sabre::authInit', $event);

// And off we go!
$server->exec();
78 changes: 78 additions & 0 deletions lib/private/User/Session.php
Expand Up @@ -31,17 +31,22 @@

namespace OC\User;

use Exception;
use OC;
use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
use OC\Authentication\Exceptions\PasswordLoginForbiddenException;
use OC\Authentication\Token\IProvider;
use OC\Authentication\Token\IToken;
use OC\Hooks\Emitter;
use OC_App;
use OC_User;
use OC_Util;
use OCA\DAV\Connector\Sabre\Auth;
use OCP\App\IAppManager;
use OCP\AppFramework\QueryException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Authentication\IAuthModule;
use OCP\IConfig;
use OCP\IRequest;
use OCP\ISession;
Expand Down Expand Up @@ -675,6 +680,79 @@ public function tryTokenLogin(IRequest $request) {
return true;
}

/**
* Tries to login with an AuthModule provided by an app
*
* @param IRequest $request The request
* @return bool True if request can be authenticated, false otherwise
* @throws Exception If the auth module could not be loaded
*/
public function tryAuthModuleLogin(IRequest $request) {
/** @var IAppManager $appManager */
$appManager = OC::$server->query('AppManager');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please inject appManager as parameter in the ctor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to inject the AppManager, but when changing the registration of UserSession in Server.php (see here) I get the following error:

PHP Fatal error:  Maximum function nesting level of '256' reached

Inside the closure for the registerService function, $appManager = $c->getAppManager(); is called over and over again. Any ideas?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No ideas?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay then let's keep it this way

$allApps = $appManager->getInstalledApps();

foreach ($allApps as $appId) {
$info = $appManager->getAppInfo($appId);

if (isset($info['auth-modules'])) {
$authModules = $info['auth-modules'];

foreach ($authModules as $class) {
try {
if (!OC_App::isAppLoaded($appId)) {
OC_App::loadApp($appId);
}

/** @var IAuthModule $authModule */
$authModule = OC::$server->query($class);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding a type check?

if ($authModule instanceof IAuthModule) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


return $this->loginUser($authModule->auth($request), $authModule->getUserPassword($request));
} catch (QueryException $exc) {
throw new Exception("Could not load the auth module $class");
}
}
}
}

return false;
}

/**
* Log an user in
*
* @param IUser $user The user
* @param String $password The user's password
* @return boolean True if the user can be authenticated, false otherwise
* @throws LoginException if an app canceld the login process or the user is not enabled
*/
private function loginUser($user, $password) {
if (is_null($user)) {
return false;
}

$this->manager->emit('\OC\User', 'preLogin', [$user, $password]);

if (!$user->isEnabled()) {
$message = \OC::$server->getL10N('lib')->t('User disabled');
throw new LoginException($message);
}

$this->setUser($user);
$this->setLoginName($user->getDisplayName());

$this->manager->emit('\OC\User', 'postLogin', [$user, $password]);

if ($this->isLoggedIn()) {
$this->prepareUserLogin(false);
} else {
$message = \OC::$server->getL10N('lib')->t('Login canceled by app');
throw new LoginException($message);
}

return true;
}

/**
* perform login using the magic cookie (remember login)
*
Expand Down
1 change: 1 addition & 0 deletions lib/private/legacy/api.php
Expand Up @@ -365,6 +365,7 @@ private static function loginUser() {
if (OC_User::handleApacheAuth()) {
self::$logoutRequired = false;
} else if ($userSession->tryTokenLogin($request)
|| $userSession->tryAuthModuleLogin($request)
|| $userSession->tryBasicAuthLogin($request)) {
self::$logoutRequired = true;
} else {
Expand Down
36 changes: 36 additions & 0 deletions lib/public/Authentication/IAuthModule.php
@@ -0,0 +1,36 @@
<?php

namespace OCP\Authentication;

use OCP\IRequest;
use OCP\IUser;

/**
* Interface IAuthModule
*
* @package OCP\Authentication
* @since 10.0.0
*/
interface IAuthModule {

/**
* Authenticates a request.
*
* @param IRequest $request The request.
*
* @return null|IUser The user if the request is authenticated, null otherwise.
* @since 10.0.0
*/
public function auth(IRequest $request);

/**
* Returns the user's password.
*
* @param IRequest $request The request.
*
* @return String The user's password.
* @since 10.0.0
*/
public function getUserPassword(IRequest $request);

}