forked from pageballoon/oc-passwordless-plugin
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Token.php
executable file
·136 lines (111 loc) · 3.55 KB
/
Token.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<?php
namespace Nocio\Passwordless\Models;
use Model;
use Hash;
use Carbon\Carbon;
use October\Rain\Exception\ApplicationException;
class Token extends Model
{
/**
* @var string The database table used by the model.
*/
public $table = 'nocio_passwordless_tokens';
/**
* Fillable fields for the model.
*
* @var array
*/
protected $guarded = ['id'];
protected $dates = ['expires'];
public $morphTo = [
'user' => []
];
/**
* Validates against a token
* @param type $token
* @return type
*/
public function validate($token) {
return Hash::check($token, $this->token);
}
/**
* Generates and returns a new token for a user object
*
* @param $user
* @param $expires Minutes or Carbon instance
* @return $token
*/
public static function generate($user, $expires = 10, $scope = 'default')
{
$identifier = str_random(12);
$token = str_random(48);
if (is_numeric($expires)) {
$expires = Carbon::now()->addMinutes($expires);
}
static::create([
'user_type' => get_class($user),
'user_id' => $user->id,
'identifier' => $identifier,
'token' => Hash::make($token),
'expires' => $expires,
'scope' => $scope
]);
return $identifier . '-' . $token;
}
/**
* Validates token and returns token user object
* @param $raw_token
* @param $delete bool If true token will be removed after parsing
* @param $scope mixed The name scope of the token
* @throws ApplicationException Invalid token
* @return Authenticated user object
*/
public static function parse($raw_token, $delete = false, $scope = null) {
// unserialize if serialized
$unserialized_token = @unserialize($raw_token, ["allowed_classes" => false]);
if ($unserialized_token === false) {
$unserialized_token = $raw_token;
}
// ensure correct format
$clean_token = preg_replace("/[^A-Za-z0-9\- ]/", '', $unserialized_token);
if (strpos($clean_token, '-') === false) {
throw new ApplicationException('Male formed token' . $clean_token);
}
list($identifier, $token) = explode('-', $clean_token);
if (!$login_token = self::lookup($identifier)->scope($scope)->valid()->first()) {
throw new ApplicationException('Token expired or not existent. Try to login again.');
}
if (!$login_token->validate($token)) {
throw new ApplicationException('Token invalid');
}
if (!$user = $login_token->user()->first()) {
throw new ApplicationException('User does not exist');
}
if ($delete) {
$login_token->delete();
}
return $user;
}
/**
* Clears all expired unused tokens
* @return int Number of deleted expired tokens
*/
public static function clearExpired() {
return self::expired()->delete();
}
public function scopeScope($query, $scope = null) {
if (! $scope) {
return $query;
}
return $query->where('scope', $scope);
}
public function scopeLookup($query, $identifier) {
return $query->where('identifier', $identifier);
}
public function scopeExpired($query) {
return $query->where('expires', '<', Carbon::now());
}
public function scopeValid($query) {
return $query->where('expires', '>=', Carbon::now());
}
}