summaryrefslogtreecommitdiff
path: root/core/classes/authenticator
diff options
context:
space:
mode:
authorGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-03-12 07:16:23 +0200
committerGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-03-12 07:16:23 +0200
commit7076343338ae3439f3c86f01144818abe8c31978 (patch)
tree794abb1e6b8f821091fd095341885496b6dad51d /core/classes/authenticator
parent47cbb529f5723b246125ae083a193e11481b89ef (diff)
downloadclassroom-7076343338ae3439f3c86f01144818abe8c31978.tar.gz
classroom-7076343338ae3439f3c86f01144818abe8c31978.tar.bz2
classroom-7076343338ae3439f3c86f01144818abe8c31978.zip
add container helpers; constuct public directory-tree
Diffstat (limited to 'core/classes/authenticator')
-rw-r--r--core/classes/authenticator/PasswordTrait.php40
-rw-r--r--core/classes/authenticator/User.php102
-rw-r--r--core/classes/authenticator/UserInterface.php15
-rw-r--r--core/classes/authenticator/UserManager.php69
-rw-r--r--core/classes/authenticator/UserManagerInterface.php21
-rw-r--r--core/classes/authenticator/UserToken.php33
-rw-r--r--core/classes/authenticator/UserTokenInterface.php13
-rw-r--r--core/classes/authenticator/info.md114
8 files changed, 407 insertions, 0 deletions
diff --git a/core/classes/authenticator/PasswordTrait.php b/core/classes/authenticator/PasswordTrait.php
new file mode 100644
index 0000000..22976d8
--- /dev/null
+++ b/core/classes/authenticator/PasswordTrait.php
@@ -0,0 +1,40 @@
+<?php
+
+
+// namespace DevCoder\Authentication\Core;
+//
+// use DevCoder\Authentication\UserInterface;
+
+/**
+ * Trait PasswordTrait
+ * @package DevCoder\Authentication\Core
+ */
+trait PasswordTrait
+{
+ private $cost = 10;
+
+ public function cryptPassword(string $plainPassword): string
+ {
+ return password_hash(
+ $plainPassword,
+ PASSWORD_BCRYPT,
+ ['cost' => $this->cost]
+ );
+ }
+
+ public function isPasswordValid(UserInterface $user, string $plainPassword): bool
+ {
+ return password_verify(
+ $plainPassword,
+ $user->getPassword()
+ );
+ }
+
+ public function setCost(int $cost): void
+ {
+ if ($cost < 4 || $cost > 12) {
+ throw new \InvalidArgumentException('Cost must be in the range of 4-31.');
+ }
+ $this->cost = $cost;
+ }
+}
diff --git a/core/classes/authenticator/User.php b/core/classes/authenticator/User.php
new file mode 100644
index 0000000..b99fa70
--- /dev/null
+++ b/core/classes/authenticator/User.php
@@ -0,0 +1,102 @@
+<?php
+
+
+// namespace DevCoder\Authentication;
+
+class User implements UserInterface
+{
+
+ // @var string
+ private $userName;
+
+ // @var string
+ private $password;
+
+ // @var array
+ private $roles = [];
+
+ // @var bool
+ private $enabled = true;
+
+
+ /** GETs
+ * -------------------------------------------------------------------------
+ */
+
+ /** getUserName
+ * @return null|string
+ */
+ public function getUsername(): ?string
+ {
+ return $this->userName;
+ }
+
+ /** getPassword
+ * @return null|string
+ */
+ public function getPassword(): ?string
+ {
+ return $this->password;
+ }
+
+ /** getRoles
+ * @return array
+ */
+ public function getRoles(): array
+ {
+ return $this->roles;
+ }
+
+ /** isEnabled
+ * @return bool
+ */
+ public function isEnabled(): bool
+ {
+ return $this->enabled;
+ }
+
+
+ /** SETs
+ * -------------------------------------------------------------------------
+ */
+
+ /** setUserName
+ * @param string $userName
+ * @return User
+ */
+ public function setUserName(string $userName): self
+ {
+ $this->userName = $userName;
+ return $this;
+ }
+
+ /** setPassword
+ * @param string $password
+ * @return User
+ */
+ public function setPassword(string $password): self
+ {
+ $this->password = $password;
+ return $this;
+ }
+
+ /** setRoles
+ * @param array $roles
+ * @return User
+ */
+ public function setRoles(array $roles): self
+ {
+ $this->roles = $roles;
+ return $this;
+ }
+
+ /**
+ * @param bool $enabled
+ * @return User
+ */
+ public function setEnabled(bool $enabled): self
+ {
+ $this->enabled = $enabled;
+ return $this;
+ }
+}
diff --git a/core/classes/authenticator/UserInterface.php b/core/classes/authenticator/UserInterface.php
new file mode 100644
index 0000000..5cc6d2d
--- /dev/null
+++ b/core/classes/authenticator/UserInterface.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Interface UserInterface
+ * @package DevCoder\Authentication
+ */
+interface UserInterface
+{
+ public function getUsername() :?string;
+
+ public function getPassword() :?string;
+
+ public function getRoles() : array;
+
+ public function isEnabled(): bool;
+} \ No newline at end of file
diff --git a/core/classes/authenticator/UserManager.php b/core/classes/authenticator/UserManager.php
new file mode 100644
index 0000000..36f0d16
--- /dev/null
+++ b/core/classes/authenticator/UserManager.php
@@ -0,0 +1,69 @@
+<?php
+
+// namespace DevCoder\Authentication\Core;
+//
+// use DevCoder\Authentication\Token\UserToken;
+// use DevCoder\Authentication\Token\UserTokenInterface;
+// use DevCoder\Authentication\UserInterface;
+
+/**
+ * Class UserManager
+ * @package DevCoder\Authentication\Core
+ */
+class UserManager implements UserManagerInterface
+{
+
+ use PasswordTrait;
+
+ public function __construct()
+ {
+ if (session_status() === PHP_SESSION_NONE) {
+ session_start();
+ }
+ }
+
+ public function getUserToken(): ?UserTokenInterface
+ {
+ $userToken = null;
+ if ($this->hasUserToken()) {
+ $userToken = unserialize($_SESSION[UserTokenInterface::DEFAULT_PREFIX_KEY]);
+ }
+
+ return $userToken;
+ }
+
+ public function hasUserToken(): bool
+ {
+ $key = UserTokenInterface::DEFAULT_PREFIX_KEY;
+ return (array_key_exists($key, $_SESSION) && unserialize($_SESSION[$key]) !== false);
+ }
+
+ public function isGranted(array $roles): bool
+ {
+ if (!is_null($userToken = $this->getUserToken())) {
+ return false;
+ }
+
+ if ($userToken->getUser() instanceof UserInterface) {
+ return (!empty(array_intersect($roles, $userToken->getUser()->getRoles())));
+ }
+
+ return false;
+ }
+
+ public function createUserToken(UserInterface $user): UserTokenInterface
+ {
+ $userToken = new UserToken($user);
+ $_SESSION[UserTokenInterface::DEFAULT_PREFIX_KEY] = $userToken->serialize();
+
+ return $userToken;
+ }
+
+ public function logout(): void
+ {
+ if ($this->hasUserToken()) {
+ unset($_SESSION[UserTokenInterface::DEFAULT_PREFIX_KEY]);
+ }
+ }
+}
+
diff --git a/core/classes/authenticator/UserManagerInterface.php b/core/classes/authenticator/UserManagerInterface.php
new file mode 100644
index 0000000..ef120c1
--- /dev/null
+++ b/core/classes/authenticator/UserManagerInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+// namespace DevCoder\Authentication\Core;
+//
+// use DevCoder\Authentication\Token\UserTokenInterface;
+// use DevCoder\Authentication\UserInterface;
+
+interface UserManagerInterface
+{
+ public function getUserToken(): ?UserTokenInterface;
+
+ public function hasUserToken(): bool;
+
+ public function createUserToken(UserInterface $user): UserTokenInterface;
+
+ public function logout(): void;
+
+ public function cryptPassword(string $plainPassword): string;
+
+ public function isPasswordValid(UserInterface $user, string $plainPassword): bool;
+}
diff --git a/core/classes/authenticator/UserToken.php b/core/classes/authenticator/UserToken.php
new file mode 100644
index 0000000..7758086
--- /dev/null
+++ b/core/classes/authenticator/UserToken.php
@@ -0,0 +1,33 @@
+<?php
+
+
+// namespace DevCoder\Authentication\Token;
+//
+// use DevCoder\Authentication\UserInterface;
+
+/**
+ * Class UserToken
+ * @package DevCoder\Authentication\Token
+ */
+class UserToken implements UserTokenInterface
+{
+ /**
+ * @var UserInterface
+ */
+ private $user;
+
+ public function __construct(UserInterface $user)
+ {
+ $this->user = $user;
+ }
+
+ public function getUser(): UserInterface
+ {
+ return $this->user;
+ }
+
+ public function serialize(): string
+ {
+ return serialize($this);
+ }
+}
diff --git a/core/classes/authenticator/UserTokenInterface.php b/core/classes/authenticator/UserTokenInterface.php
new file mode 100644
index 0000000..2a21d8f
--- /dev/null
+++ b/core/classes/authenticator/UserTokenInterface.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * Interface UserTokenInterface
+ * @package DevCoder\Authentication\Token
+ */
+interface UserTokenInterface
+{
+ const DEFAULT_PREFIX_KEY = 'user_security';
+
+ public function getUser(): UserInterface;
+
+ public function serialize(): string;
+} \ No newline at end of file
diff --git a/core/classes/authenticator/info.md b/core/classes/authenticator/info.md
new file mode 100644
index 0000000..e6d1372
--- /dev/null
+++ b/core/classes/authenticator/info.md
@@ -0,0 +1,114 @@
+# Authentication System
+
+read/ref: https://dev.to/fadymr/php-create-your-own-php-authentication-4e20
+
+also for session: https://dev.to/fadymr/php-create-a-simple-session-wrapper-class-dpk
+
+
+
+## How to use ?
+
+
+### Registration
+
+
+ // use DevCoder\Authentication\Core\UserManager;
+ // use DevCoder\Authentication\User;
+
+ // register
+ $userManager = new UserManager();
+ $req = Registry::get('REQUEST);
+
+ $password = $userManager->cryptPassword($req->POST['password']);
+
+ $user = (new User())
+ ->setUserName($req->POST['username'])
+ ->setPassword($password)
+ ->setRoles(['ROLE_USER']);
+
+ $userManager->createUserToken($user);
+
+ // check Token in Session
+ var_dump($userManager->getUserToken());
+ // object(DevCoder\Authentication\Token\UserToken)[4]
+ // private 'user' =>
+ // object(DevCoder\Authentication\User)[5]
+ // private 'userName' => string 'username' (length=8)
+ // private 'password' => string '$2y$10$iWdcmebmikUFlgKMqW7/rOmUp1DjFAuWKqdUHBhL08FZ7LL6bwRey' (length=60)
+ // private 'roles' =>
+ // array (size=1)
+ // 0 => string 'ROLE_USER' (length=9)
+ // private 'enabled' => boolean true
+
+
+## Connected or not
+
+ <?php
+
+ // use DevCoder\Authentication\Core\UserManager;
+ // use DevCoder\Authentication\User;
+
+ $userManager = new UserManager();
+ if ($userManager->hasUserToken()) {
+ // connected
+
+ $token = $userManager->getUserToken();
+ $user = $token->getUser();
+ var_dump($user);
+ // object(DevCoder\Authentication\User)[5]
+ // private 'userName' => string 'username' (length=8)
+ // private 'password' => string '$2y$10$OBobeLhdvdiftuedlv1a6e4.qF6sCG/usq5WEV4E3uB.UiS1egv/m' (length=60)
+ // private 'roles' =>
+ // array (size=1)
+ // 0 => string 'ROLE_USER' (length=9)
+ // private 'enabled' => boolean true
+
+ } else {
+ // not connected
+ }
+
+
+## Access management
+
+ $userManager = new UserManager();
+ if ($userManager->isGranted(['ROLE_ADMIN'])) {
+ //is admin
+ // return Response 200
+ }else {
+ //is not admin
+ // return Response 403
+ }
+
+ Logout
+
+ $userManager = new UserManager();
+ $userManager->logout();
+
+
+## Login
+
+ <?php
+
+ use DevCoder\Authentication\Core\UserManager;
+
+ $stmt = $pdo->prepare("SELECT * FROM users WHERE username=?");
+ $stmt->execute([$_POST['username']]);
+ $userFromDataBase = $stmt->fetch();
+ /**
+ * Hydration
+ */
+ $user = (new \Test\DevCoder\Authentication\User())
+ ->setUserName($userFromDataBase['username'])
+ ->setPassword($userFromDataBase['password'])
+ ->setRoles(json_decode($userFromDataBase['roles']))
+ ->setEnabled($userFromDataBase['active']);
+
+ $userManager = new UserManager();
+ if ($userManager->isPasswordValid($user, $_POST['password'])) {
+
+ // login OK, set Token in session
+ $userManager->createUserToken($user);
+
+ } else {
+ // login failed , return error
+ }