Skip to content

Check for cli environment #196

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

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
{
"name": "delight-im/auth",
"description": "Authentication for PHP. Simple, lightweight and secure.",
"require": {
"repositories": [
{
"type": "vcs",
"url": "https://github.com/cewlbird/PHP-Cookie.git"
}
],
"require": {
"php": ">=5.6.0",
"ext-openssl": "*",
"delight-im/base64": "^1.0",
"delight-im/cookie": "^3.1",
"delight-im/cookie": "dev-custom",
"delight-im/db": "^1.3"
},
"type": "library",
Expand All @@ -16,5 +22,6 @@
"psr-4": {
"Delight\\Auth\\": "src/"
}
}
},
"minimum-stability": "dev"
}
34 changes: 19 additions & 15 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 25 additions & 10 deletions src/Auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ final class Auth extends UserManager {
private $sessionResyncInterval;
/** @var string the name of the cookie used for the 'remember me' feature */
private $rememberCookieName;
/** @var string the name of the cookie used for the 'remember me' feature */
private $sameSite;


/**
* @param PdoDatabase|PdoDsn|\PDO $databaseConnection the database connection to operate on
Expand All @@ -41,21 +44,30 @@ final class Auth extends UserManager {
* @param int|null $sessionResyncInterval (optional) the interval in seconds after which to resynchronize the session data with its authoritative source in the database
* @param string|null $dbSchema (optional) the schema name for all database tables used by this component
*/
public function __construct($databaseConnection, $ipAddress = null, $dbTablePrefix = null, $throttling = null, $sessionResyncInterval = null, $dbSchema = null) {
public function __construct($databaseConnection, $ipAddress = null, $dbTablePrefix = null, $throttling = null, $sessionResyncInterval = null, $dbSchema = null, $sameSite = 'Strict') {
parent::__construct($databaseConnection, $dbTablePrefix, $dbSchema);

$this->ipAddress = !empty($ipAddress) ? $ipAddress : (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null);
$this->throttling = isset($throttling) ? (bool) $throttling : true;
$this->sessionResyncInterval = isset($sessionResyncInterval) ? ((int) $sessionResyncInterval) : (60 * 5);
$this->rememberCookieName = self::createRememberCookieName();
$this->sameSite = $sameSite;

$this->initSessionIfNecessary();
$this->enhanceHttpSecurity();
if(!$this->isCli()) {
$this->initSessionIfNecessary();
$this->enhanceHttpSecurity();
}

$this->processRememberDirective();
$this->resyncSessionIfNecessary();
}

/** Check if current environment is a cli s script */
private function isCli()
{
return PHP_SAPI === 'cli';
}

/** Initializes the session and sets the correct configuration */
private function initSessionIfNecessary() {
if (\session_status() === \PHP_SESSION_NONE) {
Expand All @@ -67,7 +79,7 @@ private function initSessionIfNecessary() {
\ini_set('session.use_trans_sid', 0);

// start the session (requests a cookie to be written on the client)
@Session::start();
//@Session::start($this->sameSite);
}
}

Expand Down Expand Up @@ -129,7 +141,7 @@ private function processRememberDirective() {
// the cookie and its contents have now been proven to be valid
$valid = true;

$this->onLoginSuccessful($rememberData['user'], $rememberData['email'], $rememberData['username'], $rememberData['status'], $rememberData['roles_mask'], $rememberData['force_logout'], true);
$this->onLoginSuccessful($rememberData['user'], $rememberData['email'], $rememberData['username'], $rememberData['status'], $rememberData['roles_mask'], $rememberData['force_logout'], true, $this->sameSite);
}
}
}
Expand Down Expand Up @@ -439,7 +451,7 @@ public function logOutEverywhereElse() {
$_SESSION[self::SESSION_FIELD_FORCE_LOGOUT]++;

// re-generate the session ID to prevent session fixation attacks (requests a cookie to be written on the client)
Session::regenerate(true);
Session::regenerate(true, $this->sameSite);

// if there had been an existing remember directive previously
if (isset($previousRememberDirectiveExpiry)) {
Expand Down Expand Up @@ -545,6 +557,7 @@ private function setRememberCookie($selector, $token, $expires) {
$cookie->setDomain($params['domain']);
$cookie->setHttpOnly($params['httponly']);
$cookie->setSecureOnly($params['secure']);
$cookie->setSameSiteRestriction($this->sameSite);
$result = $cookie->save();

if ($result === false) {
Expand All @@ -559,11 +572,12 @@ private function setRememberCookie($selector, $token, $expires) {
$cookie->setDomain($params['domain']);
$cookie->setHttpOnly($params['httponly']);
$cookie->setSecureOnly($params['secure']);
$cookie->setSameSiteRestriction($this->sameSite);
$cookie->delete();
}
}

protected function onLoginSuccessful($userId, $email, $username, $status, $roles, $forceLogout, $remembered) {
protected function onLoginSuccessful($userId, $email, $username, $status, $roles, $forceLogout, $remembered, $sameSite = 'Strict') {
// update the timestamp of the user's last login
try {
$this->db->update(
Expand All @@ -576,7 +590,7 @@ protected function onLoginSuccessful($userId, $email, $username, $status, $roles
throw new DatabaseError($e->getMessage());
}

parent::onLoginSuccessful($userId, $email, $username, $status, $roles, $forceLogout, $remembered);
parent::onLoginSuccessful($userId, $email, $username, $status, $roles, $forceLogout, $remembered, $sameSite);
}

/**
Expand All @@ -593,6 +607,7 @@ private function deleteSessionCookie() {
$cookie->setDomain($params['domain']);
$cookie->setHttpOnly($params['httponly']);
$cookie->setSecureOnly($params['secure']);
$cookie->setSameSiteRestriction($this->sameSite);
$result = $cookie->delete();

if ($result === false) {
Expand Down Expand Up @@ -734,7 +749,7 @@ public function confirmEmailAndSignIn($selector, $token, $rememberDuration = nul
[ 'id', 'email', 'username', 'status', 'roles_mask', 'force_logout' ]
);

$this->onLoginSuccessful($userData['id'], $userData['email'], $userData['username'], $userData['status'], $userData['roles_mask'], $userData['force_logout'], true);
$this->onLoginSuccessful($userData['id'], $userData['email'], $userData['username'], $userData['status'], $userData['roles_mask'], $userData['force_logout'], true, $this->sameSite);

if ($rememberDuration !== null) {
$this->createRememberDirective($userData['id'], $rememberDuration);
Expand Down Expand Up @@ -1070,7 +1085,7 @@ private function authenticateUserInternal($password, $email = null, $username =

if ((int) $userData['verified'] === 1) {
if (!isset($onBeforeSuccess) || (\is_callable($onBeforeSuccess) && $onBeforeSuccess($userData['id']) === true)) {
$this->onLoginSuccessful($userData['id'], $userData['email'], $userData['username'], $userData['status'], $userData['roles_mask'], $userData['force_logout'], false);
$this->onLoginSuccessful($userData['id'], $userData['email'], $userData['username'], $userData['status'], $userData['roles_mask'], $userData['force_logout'], false, $this->sameSite);

// continue to support the old parameter format
if ($rememberDuration === true) {
Expand Down
4 changes: 2 additions & 2 deletions src/UserManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,9 @@ protected function updatePasswordInternal($userId, $newPassword) {
* @param bool $remembered whether the user has been remembered (instead of them having authenticated actively)
* @throws AuthError if an internal problem occurred (do *not* catch)
*/
protected function onLoginSuccessful($userId, $email, $username, $status, $roles, $forceLogout, $remembered) {
protected function onLoginSuccessful($userId, $email, $username, $status, $roles, $forceLogout, $remembered, $sameSite = 'Strict') {
// re-generate the session ID to prevent session fixation attacks (requests a cookie to be written on the client)
Session::regenerate(true);
Session::regenerate(true, $sameSite);

// save the user data in the session variables maintained by this library
$_SESSION[self::SESSION_FIELD_LOGGED_IN] = true;
Expand Down