Split auth stuff off into own context.

This commit is contained in:
flash 2023-09-08 00:43:00 +00:00
parent c5a284f360
commit 8b0f960c86
11 changed files with 94 additions and 68 deletions

View file

@ -10,9 +10,10 @@ if($authInfo->isLoggedIn()) {
return; return;
} }
$authCtx = $msz->getAuthContext();
$users = $msz->getUsersContext()->getUsers(); $users = $msz->getUsersContext()->getUsers();
$sessions = $msz->getSessions(); $sessions = $authCtx->getSessions();
$loginAttempts = $msz->getLoginAttempts(); $loginAttempts = $authCtx->getLoginAttempts();
if(!empty($_GET['resolve'])) { if(!empty($_GET['resolve'])) {
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
@ -121,7 +122,7 @@ while(!empty($_POST['login']) && is_array($_POST['login'])) {
} }
if($userInfo->hasTOTPKey()) { if($userInfo->hasTOTPKey()) {
$tfaToken = $msz->getTFASessions()->createToken($userInfo); $tfaToken = $authCtx->getTwoFactorAuthSessions()->createToken($userInfo);
url_redirect('auth-two-factor', [ url_redirect('auth-two-factor', [
'token' => $tfaToken, 'token' => $tfaToken,
]); ]);

View file

@ -12,7 +12,8 @@ if($authInfo->isLoggedIn()) {
$tokenInfo = $authInfo->getTokenInfo(); $tokenInfo = $authInfo->getTokenInfo();
$msz->getSessions()->deleteSessions(sessionTokens: $tokenInfo->getSessionToken()); $authCtx = $msz->getAuthContext();
$authCtx->getSessions()->deleteSessions(sessionTokens: $tokenInfo->getSessionToken());
$tokenBuilder = $tokenInfo->toBuilder(); $tokenBuilder = $tokenInfo->toBuilder();
$tokenBuilder->removeUserId(); $tokenBuilder->removeUserId();

View file

@ -10,9 +10,10 @@ if($authInfo->isLoggedIn()) {
return; return;
} }
$authCtx = $msz->getAuthContext();
$users = $msz->getUsersContext()->getUsers(); $users = $msz->getUsersContext()->getUsers();
$recoveryTokens = $msz->getRecoveryTokens(); $recoveryTokens = $authCtx->getRecoveryTokens();
$loginAttempts = $msz->getLoginAttempts(); $loginAttempts = $authCtx->getLoginAttempts();
$reset = !empty($_POST['reset']) && is_array($_POST['reset']) ? $_POST['reset'] : []; $reset = !empty($_POST['reset']) && is_array($_POST['reset']) ? $_POST['reset'] : [];
$forgot = !empty($_POST['forgot']) && is_array($_POST['forgot']) ? $_POST['forgot'] : []; $forgot = !empty($_POST['forgot']) && is_array($_POST['forgot']) ? $_POST['forgot'] : [];

View file

@ -10,6 +10,7 @@ if($authInfo->isLoggedIn()) {
return; return;
} }
$authCtx = $msz->getAuthContext();
$usersCtx = $msz->getUsersContext(); $usersCtx = $msz->getUsersContext();
$users = $usersCtx->getUsers(); $users = $usersCtx->getUsers();
$roles = $usersCtx->getRoles(); $roles = $usersCtx->getRoles();
@ -31,7 +32,7 @@ $countryCode = $_SERVER['COUNTRY_CODE'] ?? 'XX';
// for fast matching // for fast matching
$restricted = ''; $restricted = '';
$loginAttempts = $msz->getLoginAttempts(); $loginAttempts = $authCtx->getLoginAttempts();
$remainingAttempts = $loginAttempts->countRemainingAttempts($ipAddress); $remainingAttempts = $loginAttempts->countRemainingAttempts($ipAddress);
while(!$restricted && !empty($register)) { while(!$restricted && !empty($register)) {

View file

@ -11,10 +11,11 @@ if($authInfo->isLoggedIn()) {
return; return;
} }
$authCtx = $msz->getAuthContext();
$users = $msz->getUsersContext()->getUsers(); $users = $msz->getUsersContext()->getUsers();
$sessions = $msz->getSessions(); $sessions = $authCtx->getSessions();
$tfaSessions = $msz->getTFASessions(); $tfaSessions = $authCtx->getTwoFactorAuthSessions();
$loginAttempts = $msz->getLoginAttempts(); $loginAttempts = $authCtx->getLoginAttempts();
$ipAddress = $_SERVER['REMOTE_ADDR']; $ipAddress = $_SERVER['REMOTE_ADDR'];
$countryCode = $_SERVER['COUNTRY_CODE'] ?? 'XX'; $countryCode = $_SERVER['COUNTRY_CODE'] ?? 'XX';

View file

@ -8,7 +8,8 @@ $currentUser = $authInfo->getUserInfo();
if($currentUser === null) if($currentUser === null)
Template::throwError(401); Template::throwError(401);
$loginAttempts = $msz->getLoginAttempts(); $authCtx = $msz->getAuthContext();
$loginAttempts = $authCtx->getLoginAttempts();
$auditLog = $msz->getAuditLog(); $auditLog = $msz->getAuditLog();
$loginHistoryPagination = new Pagination($loginAttempts->countAttempts(userInfo: $currentUser), 5, 'hp'); $loginHistoryPagination = new Pagination($loginAttempts->countAttempts(userInfo: $currentUser), 5, 'hp');

View file

@ -8,7 +8,8 @@ if(!$authInfo->isLoggedIn())
Template::throwError(401); Template::throwError(401);
$errors = []; $errors = [];
$sessions = $msz->getSessions(); $authCtx = $msz->getAuthContext();
$sessions = $authCtx->getSessions();
$currentUser = $authInfo->getUserInfo(); $currentUser = $authInfo->getUserInfo();
$activeSessionId = $authInfo->getSessionId(); $activeSessionId = $authInfo->getSessionId();

View file

@ -39,7 +39,7 @@ if(file_exists(MSZ_ROOT . '/.migrating')) {
exit; exit;
} }
$tokenPacker = $msz->createAuthTokenPacker(); $tokenPacker = $msz->getAuthContext()->createAuthTokenPacker();
if(filter_has_var(INPUT_COOKIE, 'msz_auth')) if(filter_has_var(INPUT_COOKIE, 'msz_auth'))
$tokenInfo = $tokenPacker->unpack(filter_input(INPUT_COOKIE, 'msz_auth')); $tokenInfo = $tokenPacker->unpack(filter_input(INPUT_COOKIE, 'msz_auth'));
@ -58,7 +58,7 @@ $userInfoReal = null;
if($tokenInfo->hasUserId() && $tokenInfo->hasSessionToken()) { if($tokenInfo->hasUserId() && $tokenInfo->hasSessionToken()) {
$users = $msz->getUsersContext()->getUsers(); $users = $msz->getUsersContext()->getUsers();
$sessions = $msz->getSessions(); $sessions = $msz->getAuthContext()->getSessions();
$tokenBuilder = new AuthTokenBuilder($tokenInfo); $tokenBuilder = new AuthTokenBuilder($tokenInfo);
try { try {

42
src/Auth/AuthContext.php Normal file
View file

@ -0,0 +1,42 @@
<?php
namespace Misuzu\Auth;
use Index\Data\IDbConnection;
use Misuzu\Config\IConfig;
class AuthContext {
private Sessions $sessions;
private LoginAttempts $loginAttempts;
private RecoveryTokens $recoveryTokens;
private TwoFactorAuthSessions $tfaSessions;
private IConfig $config;
public function __construct(IDbConnection $dbConn, IConfig $config) {
$this->config = $config;
$this->sessions = new Sessions($dbConn);
$this->loginAttempts = new LoginAttempts($dbConn);
$this->recoveryTokens = new RecoveryTokens($dbConn);
$this->tfaSessions = new TwoFactorAuthSessions($dbConn);
}
public function getSessions(): Sessions {
return $this->sessions;
}
public function getLoginAttempts(): LoginAttempts {
return $this->loginAttempts;
}
public function getRecoveryTokens(): RecoveryTokens {
return $this->recoveryTokens;
}
public function getTwoFactorAuthSessions(): TwoFactorAuthSessions {
return $this->tfaSessions;
}
public function createAuthTokenPacker(): AuthTokenPacker {
return new AuthTokenPacker($this->config->getString('secret', 'meow'));
}
}

View file

@ -10,12 +10,9 @@ use Index\Http\HttpRequest;
use Index\Routing\Router; use Index\Routing\Router;
use Sasae\SasaeEnvironment; use Sasae\SasaeEnvironment;
use Misuzu\Template; use Misuzu\Template;
use Misuzu\Auth\AuthContext;
use Misuzu\Auth\AuthInfo; use Misuzu\Auth\AuthInfo;
use Misuzu\Auth\AuthTokenPacker; use Misuzu\Auth\AuthTokenPacker;
use Misuzu\Auth\LoginAttempts;
use Misuzu\Auth\RecoveryTokens;
use Misuzu\Auth\Sessions;
use Misuzu\Auth\TwoFactorAuthSessions;
use Misuzu\AuditLog\AuditLog; use Misuzu\AuditLog\AuditLog;
use Misuzu\Changelog\Changelog; use Misuzu\Changelog\Changelog;
use Misuzu\Changelog\ChangelogRoutes; use Misuzu\Changelog\ChangelogRoutes;
@ -59,11 +56,7 @@ class MisuzuContext {
private Comments $comments; private Comments $comments;
private Sessions $sessions; private AuthContext $authCtx;
private LoginAttempts $loginAttempts;
private RecoveryTokens $recoveryTokens;
private TwoFactorAuthSessions $tfaSessions;
private UsersContext $usersCtx; private UsersContext $usersCtx;
private ProfileFields $profileFields; private ProfileFields $profileFields;
@ -76,22 +69,20 @@ class MisuzuContext {
$this->dbConn = $dbConn; $this->dbConn = $dbConn;
$this->config = $config; $this->config = $config;
$this->usersCtx = new UsersContext($this->dbConn); $this->perms = new Permissions($dbConn);
$this->perms = new Permissions($this->dbConn);
$this->authInfo = new AuthInfo($this->perms); $this->authInfo = new AuthInfo($this->perms);
$this->auditLog = new AuditLog($this->dbConn);
$this->changelog = new Changelog($this->dbConn); $this->authCtx = new AuthContext($dbConn, $config->scopeTo('auth'));
$this->comments = new Comments($this->dbConn); $this->usersCtx = new UsersContext($dbConn);
$this->counters = new Counters($this->dbConn);
$this->emotes = new Emotes($this->dbConn); $this->auditLog = new AuditLog($dbConn);
$this->forum = new Forum($this->dbConn); $this->changelog = new Changelog($dbConn);
$this->loginAttempts = new LoginAttempts($this->dbConn); $this->comments = new Comments($dbConn);
$this->news = new News($this->dbConn); $this->counters = new Counters($dbConn);
$this->profileFields = new ProfileFields($this->dbConn); $this->emotes = new Emotes($dbConn);
$this->recoveryTokens = new RecoveryTokens($this->dbConn); $this->forum = new Forum($dbConn);
$this->sessions = new Sessions($this->dbConn); $this->news = new News($dbConn);
$this->tfaSessions = new TwoFactorAuthSessions($this->dbConn); $this->profileFields = new ProfileFields($dbConn);
} }
public function getDbConn(): IDbConnection { public function getDbConn(): IDbConnection {
@ -139,22 +130,6 @@ class MisuzuContext {
return $this->auditLog; return $this->auditLog;
} }
public function getLoginAttempts(): LoginAttempts {
return $this->loginAttempts;
}
public function getRecoveryTokens(): RecoveryTokens {
return $this->recoveryTokens;
}
public function getTFASessions(): TwoFactorAuthSessions {
return $this->tfaSessions;
}
public function getSessions(): Sessions {
return $this->sessions;
}
public function getCounters(): Counters { public function getCounters(): Counters {
return $this->counters; return $this->counters;
} }
@ -171,6 +146,10 @@ class MisuzuContext {
return $this->perms; return $this->perms;
} }
public function getAuthContext(): AuthContext {
return $this->authCtx;
}
public function getUsersContext(): UsersContext { public function getUsersContext(): UsersContext {
return $this->usersCtx; return $this->usersCtx;
} }
@ -310,11 +289,10 @@ class MisuzuContext {
$this->router->register(new SharpChatRoutes( $this->router->register(new SharpChatRoutes(
$this->config->scopeTo('sockChat'), $this->config->scopeTo('sockChat'),
$this->usersCtx, $this->usersCtx,
$this->authCtx,
$this->emotes, $this->emotes,
$this->sessions,
$this->perms, $this->perms,
$this->authInfo, $this->authInfo
$this->createAuthTokenPacker(...)
)); ));
$this->router->register(new SatoriRoutes( $this->router->register(new SatoriRoutes(

View file

@ -1,13 +1,13 @@
<?php <?php
namespace Misuzu\SharpChat; namespace Misuzu\SharpChat;
use Closure;
use RuntimeException; use RuntimeException;
use Index\Colour\Colour; use Index\Colour\Colour;
use Index\Routing\IRouter; use Index\Routing\IRouter;
use Index\Routing\IRouteHandler; use Index\Routing\IRouteHandler;
use Index\Routing\Route; use Index\Routing\Route;
use Misuzu\Tools; use Misuzu\Tools;
use Misuzu\Auth\AuthContext;
use Misuzu\Auth\AuthInfo; use Misuzu\Auth\AuthInfo;
use Misuzu\Auth\Sessions; use Misuzu\Auth\Sessions;
use Misuzu\Config\IConfig; use Misuzu\Config\IConfig;
@ -22,11 +22,10 @@ final class SharpChatRoutes implements IRouteHandler {
public function __construct( public function __construct(
private IConfig $config, private IConfig $config,
private UsersContext $usersCtx, private UsersContext $usersCtx,
private AuthContext $authCtx,
private Emotes $emotes, private Emotes $emotes,
private Sessions $sessions,
private Permissions $perms, private Permissions $perms,
private AuthInfo $authInfo, private AuthInfo $authInfo
private Closure $createAuthTokenPacker // this sucks lol
) { ) {
$this->hashKey = $this->config->getString('hashKey', 'woomy'); $this->hashKey = $this->config->getString('hashKey', 'woomy');
} }
@ -61,7 +60,7 @@ final class SharpChatRoutes implements IRouteHandler {
} }
#[Route('GET', '/_sockchat/login')] #[Route('GET', '/_sockchat/login')]
public function getLogin($response, $request): void { public function getLogin($response, $request) {
if(!$this->authInfo->isLoggedIn()) { if(!$this->authInfo->isLoggedIn()) {
$response->redirect(url('auth-login')); $response->redirect(url('auth-login'));
return; return;
@ -104,7 +103,7 @@ final class SharpChatRoutes implements IRouteHandler {
return ['ok' => false, 'err' => 'token']; return ['ok' => false, 'err' => 'token'];
try { try {
$sessionInfo = $this->sessions->getSession(sessionToken: $tokenInfo->getSessionToken()); $sessionInfo = $this->authCtx->getSessions()->getSession(sessionToken: $tokenInfo->getSessionToken());
} catch(RuntimeException $ex) { } catch(RuntimeException $ex) {
return ['ok' => false, 'err' => 'session']; return ['ok' => false, 'err' => 'session'];
} }
@ -119,7 +118,7 @@ final class SharpChatRoutes implements IRouteHandler {
? $tokenInfo->getImpersonatedUserId() ? $tokenInfo->getImpersonatedUserId()
: $userInfo->getId(); : $userInfo->getId();
$tokenPacker = ($this->createAuthTokenPacker)(); $tokenPacker = $this->authCtx->createAuthTokenPacker();
return [ return [
'ok' => true, 'ok' => true,
@ -184,7 +183,7 @@ final class SharpChatRoutes implements IRouteHandler {
return ['success' => false, 'reason' => 'hash']; return ['success' => false, 'reason' => 'hash'];
if($authMethod === 'SESS' || $authMethod === 'Misuzu') { if($authMethod === 'SESS' || $authMethod === 'Misuzu') {
$tokenPacker = ($this->createAuthTokenPacker)(); $tokenPacker = $this->authCtx->createAuthTokenPacker();
$tokenInfo = $tokenPacker->unpack($authToken); $tokenInfo = $tokenPacker->unpack($authToken);
if($tokenInfo->isEmpty()) { if($tokenInfo->isEmpty()) {
// don't support using the raw session key for Misuzu format // don't support using the raw session key for Misuzu format
@ -196,17 +195,17 @@ final class SharpChatRoutes implements IRouteHandler {
$sessionToken = $tokenInfo->getSessionToken(); $sessionToken = $tokenInfo->getSessionToken();
try { try {
$sessionInfo = $this->sessions->getSession(sessionToken: $sessionToken); $sessionInfo = $this->authCtx->getSessions()->getSession(sessionToken: $sessionToken);
} catch(RuntimeException $ex) { } catch(RuntimeException $ex) {
return ['success' => false, 'reason' => 'token']; return ['success' => false, 'reason' => 'token'];
} }
if($sessionInfo->hasExpired()) { if($sessionInfo->hasExpired()) {
$this->sessions->deleteSessions(sessionInfos: $sessionInfo); $this->authCtx->getSessions()->deleteSessions(sessionInfos: $sessionInfo);
return ['success' => false, 'reason' => 'expired']; return ['success' => false, 'reason' => 'expired'];
} }
$this->sessions->recordSessionActivity(sessionInfo: $sessionInfo, remoteAddr: $ipAddress); $this->authCtx->getSessions()->recordSessionActivity(sessionInfo: $sessionInfo, remoteAddr: $ipAddress);
$userInfo = $this->usersCtx->getUsers()->getUser($sessionInfo->getUserId(), 'id'); $userInfo = $this->usersCtx->getUsers()->getUser($sessionInfo->getUserId(), 'id');
if($tokenInfo->hasImpersonatedUserId() && $userInfo->isSuperUser()) { if($tokenInfo->hasImpersonatedUserId() && $userInfo->isSuperUser()) {