summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold Daniels <arnold@jasny.net>2014-10-07 16:42:25 +0200
committerArnold Daniels <arnold@jasny.net>2014-10-07 16:42:36 +0200
commitc0035358fd7d5f596f232df6c8de1b2221bc6336 (patch)
tree3d5913236b4c12981ff56462210ff885cafc2f1a
parent1aa227195b44af56a31563d640291e7d557621b1 (diff)
downloadauth-c0035358fd7d5f596f232df6c8de1b2221bc6336.zip
auth-c0035358fd7d5f596f232df6c8de1b2221bc6336.tar.gz
auth-c0035358fd7d5f596f232df6c8de1b2221bc6336.tar.bz2
Made Authz more generalv1.0.0-beta2
-rw-r--r--README.md97
-rw-r--r--src/Jasny/Auth.php73
-rw-r--r--src/Jasny/Auth/Authorization.php17
-rw-r--r--src/Jasny/Auth/NoSessions.php25
-rw-r--r--src/Jasny/Auth/Sessions.php31
-rw-r--r--src/Jasny/Auth/byGroup.php3
6 files changed, 209 insertions, 37 deletions
diff --git a/README.md b/README.md
index 1d549c8..933419a 100644
--- a/README.md
+++ b/README.md
@@ -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)