Browse Source

Add token auth for OCS APIs

remotes/origin/ceph-wait-for-http
Christoph Wurst 10 years ago
committed by Thomas Müller
parent
commit
fdc2cd7554
No known key found for this signature in database GPG Key ID: A943788A3BBEC44C
  1. 2
      core/Controller/LoginController.php
  2. 8
      core/Controller/TokenController.php
  3. 4
      lib/private/Authentication/Token/DefaultToken.php
  4. 10
      lib/private/Authentication/Token/DefaultTokenProvider.php
  5. 9
      lib/private/Authentication/Token/IProvider.php
  6. 7
      lib/private/Authentication/Token/IToken.php
  7. 34
      lib/private/User/Session.php
  8. 43
      lib/private/legacy/api.php

2
core/Controller/LoginController.php

@ -172,7 +172,7 @@ class LoginController extends Controller {
if ($this->userManager->checkPassword($user, $password) === false) {
return new RedirectResponse($this->urlGenerator->linkToRoute('login#showLoginForm'));
}
$this->userSession->createSessionToken($user, $password);
$this->userSession->createSessionToken($this->request, $user, $password);
if (!is_null($redirect_url) && $this->userSession->isLoggedIn()) {
$location = OC::$server->getURLGenerator()->getAbsoluteURL(urldecode($redirect_url));
// Deny the redirect if the URL contains a @

8
core/Controller/TokenController.php

@ -68,10 +68,14 @@ class TokenController extends Controller {
*/
public function generateToken($user, $password, $name = 'unknown client') {
if (is_null($user) || is_null($password)) {
return new Response([], Http::STATUS_UNPROCESSABLE_ENTITY);
$response = new Response([]);
$response->setStatus(Http::STATUS_UNPROCESSABLE_ENTITY);
return $response;
}
if ($this->userManager->checkPassword($user, $password) === false) {
return new Response([], Http::STATUS_UNAUTHORIZED);
$response = new Response([]);
$response->setStatus(Http::STATUS_UNAUTHORIZED);
return $response;
}
$token = $this->secureRandom->generate(128);
$this->tokenProvider->generateToken($token, $user, $password, $name, IToken::PERMANENT_TOKEN);

4
lib/private/Authentication/Token/DefaultToken.php

@ -60,4 +60,8 @@ class DefaultToken extends Entity implements IToken {
return $this->id;
}
public function getUid() {
return $this->uid;
}
}

10
lib/private/Authentication/Token/DefaultTokenProvider.php

@ -83,7 +83,11 @@ class DefaultTokenProvider implements IProvider {
*
* @param DefaultToken $token
*/
public function updateToken(DefaultToken $token) {
public function updateToken(IToken $token) {
if (!($token instanceof DefaultToken)) {
throw new InvalidTokenException();
}
/** @var DefaultToken $token */
$token->setLastActivity(time());
$this->mapper->update($token);
@ -130,14 +134,14 @@ class DefaultTokenProvider implements IProvider {
/**
* @param string $token
* @throws InvalidTokenException
* @return string user UID
* @return IToken user UID
*/
public function validateToken($token) {
$this->logger->debug('validating default token <' . $token . '>');
try {
$dbToken = $this->mapper->getToken($this->hashToken($token));
$this->logger->debug('valid token for ' . $dbToken->getUid());
return $dbToken->getUid();
return $dbToken;
} catch (DoesNotExistException $ex) {
$this->logger->warning('invalid token');
throw new InvalidTokenException();

9
lib/private/Authentication/Token/IProvider.php

@ -29,7 +29,14 @@ interface IProvider {
/**
* @param string $token
* @throws InvalidTokenException
* @return string user UID
* @return IToken
*/
public function validateToken($token);
/**
* Update token activity timestamp
*
* @param DefaultToken $token
*/
public function updateToken(IToken $token);
}

7
lib/private/Authentication/Token/IToken.php

@ -36,4 +36,11 @@ interface IToken {
* @return string
*/
public function getId();
/**
* Get the user UID
*
* @return string
*/
public function getUid();
}

34
lib/private/User/Session.php

@ -37,6 +37,7 @@ use OC;
use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Token\DefaultTokenProvider;
use OC\Authentication\Token\IProvider;
use OC\Authentication\Token\IToken;
use OC\Hooks\Emitter;
use OC_User;
use OCA\DAV\Connector\Sabre\Auth;
@ -218,12 +219,7 @@ class Session implements IUserSession, Emitter {
}
// Session is valid, so the token can be refreshed
// To save unnecessary DB queries, this is only done once a minute
$lastTokenUpdate = $this->session->get('last_token_update') ? : 0;
if ($lastTokenUpdate < (time () - 60)) {
$this->tokenProvider->updateToken($token);
$this->session->set('last_token_update', time());
}
$this->updateToken($this->tokenProvider, $token);
return true;
}
@ -311,6 +307,7 @@ class Session implements IUserSession, Emitter {
/**
* Tries to login the user with HTTP Basic Authentication
* @return boolean if the login was successful
*/
public function tryBasicAuthLogin() {
if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) {
@ -327,7 +324,9 @@ class Session implements IUserSession, Emitter {
Auth::DAV_AUTHENTICATED, $this->getUser()->getUID()
);
}
return $result;
}
return false;
}
private function loginWithToken($uid) {
@ -347,11 +346,12 @@ class Session implements IUserSession, Emitter {
/**
* Create a new session token for the given user credentials
*
* @param IRequest $request
* @param string $uid user UID
* @param string $password
* @return boolean
*/
public function createSessionToken($uid, $password) {
public function createSessionToken(IRequest $request, $uid, $password) {
$this->session->regenerateId();
if (is_null($this->manager->get($uid))) {
// User does not exist
@ -372,11 +372,12 @@ class Session implements IUserSession, Emitter {
private function validateToken(IRequest $request, $token) {
foreach ($this->tokenProviders as $provider) {
try {
$user = $provider->validateToken($token);
if (!is_null($user)) {
$result = $this->loginWithToken($user);
$token = $provider->validateToken($token);
if (!is_null($token)) {
$result = $this->loginWithToken($token->getUid());
if ($result) {
// Login success
$this->updateToken($provider, $token);
return true;
}
}
@ -387,6 +388,19 @@ class Session implements IUserSession, Emitter {
return false;
}
/**
* @param IProvider $provider
* @param IToken $token
*/
private function updateToken(IProvider $provider, IToken $token) {
// To save unnecessary DB queries, this is only done once a minute
$lastTokenUpdate = $this->session->get('last_token_update') ? : 0;
if ($lastTokenUpdate < (time () - 60)) {
$provider->updateToken($token);
$this->session->set('last_token_update', time());
}
}
/**
* Tries to login the user with auth token header
*

43
lib/private/legacy/api.php

@ -337,7 +337,7 @@ class OC_API {
}
// reuse existing login
$loggedIn = OC_User::isLoggedIn();
$loggedIn = \OC::$server->getUserSession()->isLoggedIn();
if ($loggedIn === true) {
$ocsApiRequest = isset($_SERVER['HTTP_OCS_APIREQUEST']) ? $_SERVER['HTTP_OCS_APIREQUEST'] === 'true' : false;
if ($ocsApiRequest) {
@ -353,35 +353,24 @@ class OC_API {
// basic auth - because OC_User::login will create a new session we shall only try to login
// if user and pass are set
if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']) ) {
$authUser = $_SERVER['PHP_AUTH_USER'];
$authPw = $_SERVER['PHP_AUTH_PW'];
try {
$return = OC_User::login($authUser, $authPw);
} catch (\OC\User\LoginException $e) {
return false;
$userSession = \OC::$server->getUserSession();
try {
$loginSuccess = $userSession->tryTokenLogin();
if (!$loginSuccess) {
$loginSuccess = $userSession->tryBasicAuthLogin();
}
if ($return === true) {
self::$logoutRequired = true;
// initialize the user's filesystem
\OC_Util::setUpFS(\OC_User::getUser());
self::$isLoggedIn = true;
} catch (\OC\User\LoginException $e) {
return false;
}
if ($loginSuccess === true) {
self::$logoutRequired = true;
/**
* Add DAV authenticated. This should in an ideal world not be
* necessary but the iOS App reads cookies from anywhere instead
* only the DAV endpoint.
* This makes sure that the cookies will be valid for the whole scope
* @see https://github.com/owncloud/core/issues/22893
*/
\OC::$server->getSession()->set(
\OCA\DAV\Connector\Sabre\Auth::DAV_AUTHENTICATED,
\OC::$server->getUserSession()->getUser()->getUID()
);
// initialize the user's filesystem
\OC_Util::setUpFS(\OC_User::getUser());
self::$isLoggedIn = true;
return \OC_User::getUser();
}
return \OC_User::getUser();
}
return false;

Loading…
Cancel
Save