diff options
author | Arnold Daniels <arnold@jasny.net> | 2014-10-07 16:42:25 +0200 |
---|---|---|
committer | Arnold Daniels <arnold@jasny.net> | 2014-10-07 16:42:36 +0200 |
commit | c0035358fd7d5f596f232df6c8de1b2221bc6336 (patch) | |
tree | 3d5913236b4c12981ff56462210ff885cafc2f1a | |
parent | 1aa227195b44af56a31563d640291e7d557621b1 (diff) | |
download | auth-c0035358fd7d5f596f232df6c8de1b2221bc6336.zip auth-c0035358fd7d5f596f232df6c8de1b2221bc6336.tar.gz auth-c0035358fd7d5f596f232df6c8de1b2221bc6336.tar.bz2 |
Made Authz more generalv1.0.0-beta2
-rw-r--r-- | README.md | 97 | ||||
-rw-r--r-- | src/Jasny/Auth.php | 73 | ||||
-rw-r--r-- | src/Jasny/Auth/Authorization.php | 17 | ||||
-rw-r--r-- | src/Jasny/Auth/NoSessions.php | 25 | ||||
-rw-r--r-- | src/Jasny/Auth/Sessions.php | 31 | ||||
-rw-r--r-- | src/Jasny/Auth/byGroup.php | 3 |
6 files changed, 209 insertions, 37 deletions
@@ -19,22 +19,13 @@ Setup `fetchUserByUsername`. Also set the `$secret` property to a [randomly selected](https://www.random.org/passwords/) string. -By default 2 authentication levels are defined, normal users (user) and admin users (admin). You can change/add levels -by overwriting the `$level` property. +You also need to specify how the current user is persisted across requests. If you want to use normal PHP sessions, you +can simply use the `Auth\Sessions` trait. ```php class Auth extends Jasny\Auth { - /** - * Authorization levels - * @var array - */ - protected static $levels = [ - 1 => 'user', - 10 => 'moderator', - 20 => 'admin', - 50 => 'superadmin' - ]; + use Auth\Sessions; /** * Secret word for creating a verification hash @@ -107,7 +98,7 @@ class User implements Jasny\Auth\User * * @return int */ - public function getSecurityLevel() + public function getRole() { return $this->security_level; } @@ -126,29 +117,103 @@ class User implements Jasny\Auth\User return true; } + + /** + * Event called on logout. + */ + public function onLogout() + { + $this->last_logout = new DateTime(); + $this->save(); + } } ``` +### Authorization +By default the `Auth` class only does authentication. Authorization can be added by impelmenting the `authorize` +method. + +Two traits are predefined to do Authorization: `Auth\byLevel` and `Auth\byGroup`. + +#### by level +The `Auth\byLevel` traits implements authorization based on access levels. Each user get permissions for it's level and +all levels below. + +```php +class Auth extends Jasny\Auth implements Jasny\Auth\Authorization +{ + use Jasny\Auth\byLevel; + + /** + * Authorization levels + * @var array + */ + protected static $levels = [ + 1 => 'user', + 10 => 'moderator', + 20 => 'admin', + 50 => 'superadmin' + ]; +} +``` + +#### by level +The `Auth\byLevel` traits implements authorization using access. An access group may supersede other groups. + +```php +class Auth extends Jasny\Auth implements Jasny\Auth\Authorization +{ + use Jasny\Auth\byGroup; + + /** + * Authorization groups and each group is supersedes. + * @var array + */ + protected static $groups = [ + 'users' => [], + 'managers' => [], + 'employees' => ['user'], + 'developers' => ['employees'], + 'paralegals' => ['employees'], + 'lawyers' => ['paralegals'], + 'lead-developers' => ['developers', 'managers'], + 'firm-partners' => ['lawyers', 'managers'] + ]; +} +``` + + Usage --- -### Basic methods +### Authentication + +Verify username and password + + Auth::verify($username, $password); Login with username and password Auth::login($username, $password); +Set user without verification + + Auth::setUser($user); + Logout Auth::logout(); -Get logged in user +Get current user Auth::user(); + +### Authorization + Check if user is allowed to do something - if (!Auth::forLevel('admin')) die("Not allowed"); + if (!Auth::authorized('admin')) die("Not allowed"); ### Signup confirmation diff --git a/src/Jasny/Auth.php b/src/Jasny/Auth.php index 2322301..5966165 100644 --- a/src/Jasny/Auth.php +++ b/src/Jasny/Auth.php @@ -40,6 +40,19 @@ abstract class Auth /** + * Persist the current user id across requests + */ + abstract protected static function persistCurrentUser(); + + /** + * Get current authenticated user id + * + * @return mixed + */ + abstract protected static function getCurrentUserId(); + + + /** * Generate a password * * @param string $password @@ -49,32 +62,36 @@ abstract class Auth { return isset($salt) ? crypt($password, $salt) : password_hash($password, PASSWORD_BCRYPT); } + /** - * Login with username and password + * Fetch user and verify password * - * @param string $username - * @param string $password - * @return boolean + * @return User|false */ - public static function login($username, $password) + public static function verify($username, $password) { $user = static::fetchUserByUsername($username); - if (!isset($user) || $user->getPassword() !== self::password($password, $user->getPassword())) return false; - return static::setUser($user); + if (!isset($user) || $user->getPassword() !== static::password($password, $user->getPassword())) return false; + return $user; } /** - * Logout + * Login with username and password + * + * @param string $username + * @param string $password + * @return boolean */ - public static function logout() + public static function login($username, $password) { - self::$user = null; - unset($_SESSION['auth_uid']); + $user = static::verify($username, $password); + if (!$user) return null; + + return static::setUser($user); } - /** * Set the current user * @@ -86,10 +103,25 @@ abstract class Auth if (!$user->onLogin()) return false; self::$user = $user; - $_SESSION['auth_uid'] = $user->getId(); + static::storeCurrentUser(); + return true; } - + + /** + * Logout + */ + public static function logout() + { + $user = static::user(); + if (!$user) return; + + $user->onLogout(); + + static::$user = null; + static::storeCurrentUser(); + } + /** * Get current authenticated user * @@ -97,11 +129,12 @@ abstract class Auth */ public static function user() { - if (!isset(self::$user) && isset($_SESSION['auth_uid'])) { - self::$user = static::fetchUserById($_SESSION['auth_uid']); + if (!isset(static::$user)) { + $uid = static::getCurrentUserId(); + if ($uid) static::$user = static::fetchUserById($uid); } - return self::$user; + return static::$user; } @@ -126,7 +159,7 @@ abstract class Auth { $id = $user->getId(); - return sprintf('%010s', substr(base_convert(md5($id . self::getSecret()), 16, 36), -10) . + return sprintf('%010s', substr(base_convert(md5($id . static::getSecret()), 16, 36), -10) . base_convert($id, 10, 36)); } @@ -139,7 +172,7 @@ abstract class Auth public function fetchForConfirmation($hash) { $id = base_convert(substr($hash, 10), 36, 10); - if (self::generateConfirmationHash($id) != $hash) return null; // invalid hash + if (static::generateConfirmationHash($id) != $hash) return null; // invalid hash return static::fetchUserById($id); } @@ -170,7 +203,7 @@ abstract class Auth $id = base_convert(substr($hash, 10), 36, 10); $user = static::fetchUserById($id); - if (!$user || self::generatePasswordResetHash($id, $user->getPassword()) != $hash) return null; // invalid hash + if (!$user || static::generatePasswordResetHash($id, $user->getPassword()) != $hash) return null; // invalid hash return $user; } diff --git a/src/Jasny/Auth/Authorization.php b/src/Jasny/Auth/Authorization.php new file mode 100644 index 0000000..034967f --- /dev/null +++ b/src/Jasny/Auth/Authorization.php @@ -0,0 +1,17 @@ +<?php + +namespace Jasny\Auth; + +/** + * Authorization is supported + */ +interface Authorization +{ + /** + * Check if user had specified role. + * + * @param mixed $role + * @return boolean + */ + public static function authorize($role); +} diff --git a/src/Jasny/Auth/NoSessions.php b/src/Jasny/Auth/NoSessions.php new file mode 100644 index 0000000..82d106d --- /dev/null +++ b/src/Jasny/Auth/NoSessions.php @@ -0,0 +1,25 @@ +<?php + +namespace Jasny\Auth; + +/** + * Don't persist the authenticated user + */ +trait NoSessions +{ + /** + * Don't persist + */ + protected static function persistCurrentUser() + { } + + /** + * There is never a persisted user id + * + * @return null + */ + protected static function getCurrentUserId() + { + return null; + } +} diff --git a/src/Jasny/Auth/Sessions.php b/src/Jasny/Auth/Sessions.php new file mode 100644 index 0000000..3e2ba3a --- /dev/null +++ b/src/Jasny/Auth/Sessions.php @@ -0,0 +1,31 @@ +<?php + +namespace Jasny\Auth; + +/** + * Use PHP sessions to persist the authenticated user + */ +trait Sessions +{ + /** + * Store the current user id in the session + */ + protected static function persistCurrentUser() + { + if (static::$user) { + $_SESSION['auth_uid'] = static::$user->getId(); + } else { + unset($_SESSION['auth_uid']); + } + } + + /** + * Get current authenticated user id for the session + * + * @return mixed + */ + protected static function getCurrentUserId() + { + return $_SESSION['auth_uid']; + } +} diff --git a/src/Jasny/Auth/byGroup.php b/src/Jasny/Auth/byGroup.php index 2fd5c54..54b343a 100644 --- a/src/Jasny/Auth/byGroup.php +++ b/src/Jasny/Auth/byGroup.php @@ -43,6 +43,7 @@ trait byGroup /** * Get group and all groups it embodies. * + * @param string $group * @return array */ public static function expandGroup($group) @@ -63,7 +64,7 @@ trait byGroup /** * Check if user is in specified access group. * - * @param int $group + * @param string $group * @return boolean */ public static function authorize($group) |