2019-12-03 13:57:53 -05:00
< ? php
declare ( strict_types = 1 );
2019-11-25 09:59:55 -05:00
2016-11-08 03:15:02 -05:00
/**
2024-05-23 03:26:56 -04:00
* SPDX - FileCopyrightText : 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX - License - Identifier : AGPL - 3.0 - or - later
2016-11-08 03:15:02 -05:00
*/
namespace OC\Authentication\LoginCredentials ;
use OC\Authentication\Exceptions\PasswordlessTokenException ;
use OC\Authentication\Token\IProvider ;
2024-10-28 01:52:36 -04:00
use OC\Security\Crypto ;
2016-11-08 03:15:02 -05:00
use OCP\Authentication\Exceptions\CredentialsUnavailableException ;
2024-01-04 06:20:14 -05:00
use OCP\Authentication\Exceptions\InvalidTokenException ;
2016-11-08 03:15:02 -05:00
use OCP\Authentication\LoginCredentials\ICredentials ;
use OCP\Authentication\LoginCredentials\IStore ;
use OCP\ISession ;
use OCP\Session\Exceptions\SessionNotAvailableException ;
2017-01-02 04:04:55 -05:00
use OCP\Util ;
2020-10-12 11:14:25 -04:00
use Psr\Log\LoggerInterface ;
2016-11-08 03:15:02 -05:00
class Store implements IStore {
/** @var ISession */
private $session ;
2020-10-12 11:14:25 -04:00
/** @var LoggerInterface */
2016-11-08 03:15:02 -05:00
private $logger ;
2017-01-02 05:57:05 -05:00
/** @var IProvider|null */
private $tokenProvider ;
2024-10-28 01:52:36 -04:00
/** @var Crypto|null */
private $crypto ;
2020-10-12 11:14:25 -04:00
public function __construct ( ISession $session ,
LoggerInterface $logger ,
2024-10-28 01:52:36 -04:00
? IProvider $tokenProvider = null ,
? Crypto $crypto = null ) {
2016-11-08 03:15:02 -05:00
$this -> session = $session ;
$this -> logger = $logger ;
2017-01-02 05:57:05 -05:00
$this -> tokenProvider = $tokenProvider ;
2024-10-28 01:52:36 -04:00
$this -> crypto = $crypto ;
2017-01-02 04:04:55 -05:00
Util :: connectHook ( 'OC_User' , 'post_login' , $this , 'authenticate' );
}
/**
* Hook listener on post login
*
* @ param array $params
*/
public function authenticate ( array $params ) {
2024-10-28 01:52:36 -04:00
$params [ 'password' ] = $this -> crypto -> encrypt (( string ) $params [ 'password' ]);
2017-01-02 04:04:55 -05:00
$this -> session -> set ( 'login_credentials' , json_encode ( $params ));
2016-11-08 03:15:02 -05:00
}
2016-11-19 10:33:19 -05:00
/**
* Replace the session implementation
*
* @ param ISession $session
*/
public function setSession ( ISession $session ) {
$this -> session = $session ;
}
2016-11-08 03:15:02 -05:00
/**
2016-12-19 05:27:42 -05:00
* @ since 12
2016-11-08 03:15:02 -05:00
*
* @ return ICredentials the login credentials of the current user
* @ throws CredentialsUnavailableException
*/
2019-11-25 09:59:55 -05:00
public function getLoginCredentials () : ICredentials {
if ( $this -> tokenProvider === null ) {
2017-01-02 05:57:05 -05:00
throw new CredentialsUnavailableException ();
}
2017-01-02 04:04:55 -05:00
$trySession = false ;
2016-11-08 03:15:02 -05:00
try {
$sessionId = $this -> session -> getId ();
$token = $this -> tokenProvider -> getToken ( $sessionId );
$uid = $token -> getUID ();
$user = $token -> getLoginName ();
$password = $this -> tokenProvider -> getPassword ( $token , $sessionId );
return new Credentials ( $uid , $user , $password );
} catch ( SessionNotAvailableException $ex ) {
2022-04-04 10:23:05 -04:00
$this -> logger -> debug ( 'could not get login credentials because session is unavailable' , [ 'app' => 'core' , 'exception' => $ex ]);
2016-11-08 03:15:02 -05:00
} catch ( InvalidTokenException $ex ) {
2022-06-01 04:31:19 -04:00
$this -> logger -> debug ( 'could not get login credentials because the token is invalid: ' . $ex -> getMessage (), [ 'app' => 'core' ]);
2017-01-02 04:04:55 -05:00
$trySession = true ;
2016-11-08 03:15:02 -05:00
} catch ( PasswordlessTokenException $ex ) {
2022-04-04 10:23:05 -04:00
$this -> logger -> debug ( 'could not get login credentials because the token has no password' , [ 'app' => 'core' , 'exception' => $ex ]);
2017-01-02 04:04:55 -05:00
$trySession = true ;
}
if ( $trySession && $this -> session -> exists ( 'login_credentials' )) {
2020-09-07 05:21:16 -04:00
/** @var array $creds */
$creds = json_decode ( $this -> session -> get ( 'login_credentials' ), true );
2024-10-28 01:52:36 -04:00
$creds [ 'password' ] = $this -> crypto -> decrypt ( $creds [ 'password' ]);
2020-09-07 05:21:16 -04:00
return new Credentials (
$creds [ 'uid' ],
$creds [ 'loginName' ] ? ? $this -> session -> get ( 'loginname' ) ? ? $creds [ 'uid' ], // Pre 20 didn't have a loginName property, hence fall back to the session value and then to the UID
$creds [ 'password' ]
);
2016-11-08 03:15:02 -05:00
}
2017-01-02 04:04:55 -05:00
2016-11-08 03:15:02 -05:00
// If we reach this line, an exception was thrown.
throw new CredentialsUnavailableException ();
}
}