Skip to content

Commit 6142939

Browse files
author
mostafa
committedDec 4, 2019
daktari
1 parent 87f098b commit 6142939

File tree

9 files changed

+629
-0
lines changed

9 files changed

+629
-0
lines changed
 

‎composer.json

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"name": "code4mk/kauth",
3+
"description": "kauth is JWT API Authentication ( jwt-auth ) for laravel",
4+
"keywords": [
5+
"jwt",
6+
"jwt-auth",
7+
"laravel",
8+
"laravel-jwt",
9+
"auth",
10+
"code4mk",
11+
"0devco",
12+
"api"
13+
],
14+
"homepage": "https://github.com/code4mk/kauth",
15+
"support": {
16+
"issues": "https://github.com/code4mk/kauth/issues",
17+
"source": "https://github.com/code4mk/kauth"
18+
},
19+
"license": "MIT",
20+
"authors": [
21+
{
22+
"name": "code4mk",
23+
"email": "hiremostafa@gmail.com",
24+
"website": "https://code4mk.org"
25+
}
26+
],
27+
"require": {
28+
"firebase/php-jwt": "^5.0"
29+
},
30+
"autoload": {
31+
"psr-4": {
32+
"Kauth\\": "src/"
33+
}
34+
},
35+
"extra": {
36+
"laravel": {
37+
"providers": [
38+
"Kauth\\KauthServiceProvider"
39+
]
40+
}
41+
},
42+
"prefer-stable": true,
43+
"minimum-stability": "dev"
44+
}

‎config/kauth.php

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
return [
4+
/*
5+
|--------------------------------------------------------------------------
6+
| Kauth token key name
7+
|--------------------------------------------------------------------------
8+
|
9+
| You can set your desired token key name for request header
10+
| client side / axios headers name as (Authorization)
11+
| default is tokon
12+
*/
13+
14+
"token_header_name" => "",
15+
16+
/*
17+
|--------------------------------------------------------------------------
18+
| Kauth token expired duration
19+
|--------------------------------------------------------------------------
20+
|
21+
| You can set duration of your token
22+
| pattern will be follow P7Y5M4DT4H3M2S
23+
| http://php.net/manual/en/datetime.gettimestamp.php
24+
*/
25+
26+
"token_exp" => "",
27+
28+
/*
29+
|--------------------------------------------------------------------------
30+
| Kauth jwt payload iss and aud
31+
|--------------------------------------------------------------------------
32+
|
33+
| You can set jwt iss
34+
|
35+
| your url host name
36+
*/
37+
"payload" => [
38+
"iss" => ""
39+
],
40+
41+
/*
42+
|--------------------------------------------------------------------------
43+
| Kauth cookie auth
44+
|--------------------------------------------------------------------------
45+
|
46+
| You can use for socialite system
47+
|
48+
|
49+
*/
50+
51+
"cookie_auth" => false,
52+
53+
/*
54+
|--------------------------------------------------------------------------
55+
| Kauth guard setup
56+
|--------------------------------------------------------------------------
57+
|
58+
| You can set guard
59+
| set table name
60+
|
61+
*/
62+
63+
"guard" => [
64+
"users" => [
65+
"table" => "users",
66+
],
67+
],
68+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\Schema;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Database\Migrations\Migration;
6+
7+
class CreateKauthTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::create('kauth', function (Blueprint $table) {
17+
$table->increments('id');
18+
$table->text('tokon')->nullable();
19+
$table->integer('user_id')->nullable();
20+
$table->integer('iat')->nullable();
21+
$table->integer('exp')->nullable();
22+
$table->string('ip')->nullable();
23+
$table->string('browser')->nullable();
24+
$table->string('device')->nullable();
25+
$table->string('os')->nullable();
26+
$table->string('login')->nullable();
27+
$table->string('guard')->nullable();
28+
$table->string('user_type')->nullable();
29+
$table->boolean('active')->default(true);
30+
$table->timestamps();
31+
});
32+
}
33+
34+
/**
35+
* Reverse the migrations.
36+
*
37+
* @return void
38+
*/
39+
public function down()
40+
{
41+
Schema::dropIfExists('kauth');
42+
}
43+
}

‎src/Auth/Auth.php

+295
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
<?php
2+
3+
namespace Kauth\Auth;
4+
5+
/**
6+
* @author @code4mk <hiremostafa@gmail.com>
7+
* @author @0devco <with@0dev.co>
8+
* @since 2019
9+
* @copyright 0dev.co (https://0dev.co)
10+
*/
11+
12+
use Illuminate\Http\Request;
13+
use Kauth\Model\KauthModel;
14+
use Kauth\Token\Token;
15+
use DateTime;
16+
use Schema;
17+
use Config;
18+
use Hash;
19+
use DB;
20+
use Parrotx\Dakapi\App\Http\Controllers\Controller;
21+
class Auth extends Controller
22+
{
23+
24+
protected $guard;
25+
26+
protected $socialite;
27+
28+
protected $user_type = '';
29+
30+
protected $daktariApp = false;
31+
32+
public function __construct()
33+
{
34+
$this->guard();
35+
$this->socialite(false);
36+
}
37+
38+
public function daktariui()
39+
{
40+
$this->daktariApp = true;
41+
return $this;
42+
}
43+
44+
45+
/**
46+
*
47+
* set gaurd name
48+
*
49+
*@return string guard
50+
*/
51+
public function guard($guard ='users')
52+
{
53+
$this->guard = $guard;
54+
return $this;
55+
}
56+
57+
/**
58+
*
59+
* socialite system
60+
*
61+
*@return boolean
62+
*/
63+
public function socialite($status = true)
64+
{
65+
$this->socialite = $status;
66+
return $this;
67+
}
68+
69+
70+
/**
71+
*
72+
* attempt credentials
73+
*
74+
*@return string jwt
75+
*/
76+
public function attempt($credentials)
77+
{
78+
$credential = [];
79+
$getTokennames = $credentials['usernames'] ?? [];
80+
$getTokenname = $credentials['username'] ?? '';
81+
82+
// store credentials without password & username
83+
84+
foreach ($credentials as $key => $value){
85+
if($key === 'password' || !empty($key === 'usernames') || !empty($key === 'username')){
86+
// nothing
87+
} else {
88+
$credential[$key] = $value;
89+
}
90+
}
91+
92+
// fetch user by credentials
93+
94+
$getToken = DB::table(Config::get('kauth.guard.' . $this->guard . '.table'))
95+
// multiple username accept (id||username||email >> etc)
96+
->where(function ($query) use ($getTokennames,$getTokenname){
97+
foreach ($getTokennames as $key => $value) {
98+
$query->orWhere($value,$getTokenname)
99+
->orWhere($value,$getTokenname);
100+
}
101+
})
102+
->where(function ($query) use ($credential) {
103+
foreach ($credential as $key => $value) {
104+
$query->where($key,$value);
105+
}
106+
})
107+
->first();
108+
109+
110+
// check has user and socialite
111+
112+
if(!empty($getToken) && !($this->socialite)){
113+
$getTokenPassword = Hash::check($credentials['password'],$getToken->password);
114+
} elseif (!empty($getToken) && $this->socialite) {
115+
$getTokenPassword = true;
116+
} else {
117+
$getTokenPassword = false;
118+
}
119+
120+
// check user and password then store jwt token
121+
122+
if (!empty($getToken) && $getTokenPassword ) {
123+
$jwt = new KauthModel;
124+
if($this->daktariApp && $getToken->type == 'doctor'){
125+
$jwt->user_id = $getToken->doctor_id;
126+
$jwt->user_type = $getToken->type;
127+
}elseif ($this->daktariApp && $getToken->type == 'patient') {
128+
$jwt->user_id = $getToken->patient_id;
129+
$jwt->user_type = $getToken->type;
130+
}else{
131+
$jwt->user_id = $getToken->id;
132+
}
133+
134+
$jwt->browser = \Request::get('browser');
135+
$jwt->os = \Request::get('os');
136+
$jwt->device = \Request::get('device');
137+
$jwt->ip = \Request::get('ip');
138+
$jwt->active = true;
139+
$jwt->guard = $this->guard;
140+
$jwt->save();
141+
142+
$secret = new Token();
143+
if (Schema::hasColumn(Config::get('kauth.guard.' . $this->guard . '.table'), 'user_type')) {
144+
$this->user_type = $getToken->user_type;
145+
}
146+
$tokon = $secret->create($jwt->id,$this->user_type);
147+
$payloader = $secret->payloader($tokon);
148+
$jwt->tokon = $tokon;
149+
$jwt->iat = $payloader['iat'];
150+
$jwt->exp = $payloader['expM'];
151+
152+
153+
if (Schema::hasColumn($this->guard, 'user_type')) {
154+
$jwt->user_type = $getToken->user_type;
155+
}
156+
$jwt->save();
157+
return [
158+
'token' => $jwt->tokon,
159+
'type' => $getToken->type,
160+
'did' => $getToken->doctor_id,
161+
'pid' => $getToken->patient_id
162+
];
163+
}
164+
return "wrong credentials";
165+
}
166+
167+
/**
168+
*
169+
* auth check
170+
*
171+
*@return boolean
172+
*/
173+
public function check()
174+
{
175+
try {
176+
$token = new Token();
177+
$getToken = KauthModel::where('tokon',$token->tokon())->first();
178+
$instanceTime = new DateTime();
179+
if(!empty($getToken) && ($instanceTime->getTimestamp() <= $getToken->exp)){
180+
return true;
181+
}
182+
return false;
183+
} catch (\Exception $e) {
184+
return "jwt-error";
185+
}
186+
187+
}
188+
189+
/**
190+
*
191+
* auth user id
192+
*
193+
*@return integer id
194+
*/
195+
public function id()
196+
{
197+
try {
198+
$token = new Token();
199+
$getToken = KauthModel::where('tokon',$token->tokon())->first();
200+
$instanceTime = new DateTime();
201+
if(!empty($getToken) && ($instanceTime->getTimestamp() <= $getToken->exp)){
202+
if($this->daktariApp){
203+
$attribute = [
204+
"id" => $getToken->user_id,
205+
"type" => $getToken->user_type
206+
];
207+
}else{
208+
$attribute = $getToken->user_id;
209+
}
210+
211+
return $attribute;
212+
}
213+
return 0;
214+
} catch (\Exception $e) {
215+
return "jwt-error";
216+
}
217+
218+
}
219+
220+
public function auths()
221+
{
222+
$auths = KauthModel::where('user_id',$this->id())
223+
->orderBy('id','desc')
224+
->get();
225+
return $auths;
226+
}
227+
228+
/**
229+
*
230+
* auth logout
231+
*
232+
* delete auth credentials
233+
*/
234+
public function logout()
235+
{
236+
try {
237+
$token = new Token();
238+
$getToken = KauthModel::where('tokon',$token->tokon())->first();
239+
$getToken->delete();
240+
} catch (\Exception $e) {
241+
return "jwt-error";
242+
}
243+
244+
245+
}
246+
247+
/**
248+
*
249+
* logout all devices
250+
*
251+
* delete auth user's all token
252+
* without current token id
253+
*/
254+
public function logoutOtherDevices()
255+
{
256+
try {
257+
$token = new Token();
258+
$getToken = KauthModel::where('tokon',$token->tokon())->first();
259+
260+
// fetch all token without current token
261+
262+
KauthModel::where('user_id',$getToken->user_id)
263+
-> where(function ($query) use ($getToken){
264+
$query->whereNotIn('id',[$getToken->id]);
265+
})
266+
->delete();
267+
} catch (\Exception $e) {
268+
return "jwt-error";
269+
}
270+
271+
}
272+
273+
/**
274+
*
275+
* refresh token
276+
*
277+
* edit existing token
278+
*
279+
*/
280+
public function refreshToken()
281+
{
282+
try {
283+
$token = new Token();
284+
$getToken = KauthModel::where('tokon',$token->tokon())->first();
285+
$getToken->tokon = $token->create($getToken->id);
286+
$payloader = $token->payloader($token->create($getToken->id));
287+
$getToken->iat = $payloader['iat'];
288+
$getToken->exp = $payloader['expM'];
289+
$getToken->save();
290+
return $getToken->tokon;
291+
} catch (\Exception $e) {
292+
return "jwt-error";
293+
}
294+
}
295+
}

‎src/Facades/Auth.php

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Kauth\Facades;
4+
5+
/**
6+
* @author @code4mk <hiremostafa@gmail.com>
7+
* @author @0devco <with@0dev.co>
8+
* @since 2019
9+
* @copyright 0dev.co (https://0dev.co)
10+
*/
11+
12+
use Illuminate\Support\Facades\Facade;
13+
14+
class Auth extends Facade
15+
{
16+
/**
17+
* Get the registered name of the component.
18+
*
19+
* @return string
20+
*/
21+
protected static function getFacadeAccessor()
22+
{
23+
return 'kauth';
24+
}
25+
}

‎src/KauthServiceProvider.php

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace Kauth;
4+
5+
/**
6+
* @author @code4mk <hiremostafa@gmail.com>
7+
* @author @0devco <with@0dev.co>
8+
* @since 2019
9+
* @copyright 0dev.co (https://0dev.co)
10+
*/
11+
12+
use Illuminate\Support\ServiceProvider;
13+
use Illuminate\Foundation\AliasLoader;
14+
use Kauth\Auth\Auth;
15+
16+
class KauthServiceProvider extends ServiceProvider
17+
{
18+
/**
19+
* Bootstrap any application services.
20+
*
21+
* @return void
22+
*/
23+
public function boot()
24+
{
25+
// publish database
26+
$this->publishes([
27+
__DIR__ . '/../migrations/' => base_path('/database/migrations'),
28+
], 'migrations');
29+
// publish config
30+
$this->publishes([
31+
__DIR__ . '/../config/kauth.php' => config_path('kauth.php'),
32+
], 'config');
33+
//load alias
34+
AliasLoader::getInstance()->alias('Kauth', 'Kauth\Facades\Auth');
35+
}
36+
37+
/**
38+
* Register any application services.
39+
*
40+
* @return void
41+
*/
42+
public function register()
43+
{
44+
$this->app->bind('kauth', function () {
45+
return new Auth;
46+
});
47+
}
48+
}

‎src/Model/KauthModel.php

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Kauth\Model;
4+
5+
/**
6+
* @author @code4mk <hiremostafa@gmail.com>
7+
* @author @0devco <with@0dev.co>
8+
* @since 2019
9+
* @copyright 0dev.co (https://0dev.co)
10+
*/
11+
12+
use Illuminate\Database\Eloquent\Model;
13+
14+
class KauthModel extends Model
15+
{
16+
/**
17+
* The table associated with the model.
18+
*
19+
* @var string
20+
*/
21+
protected $table = 'kauth';
22+
}

‎src/Token/Token.php

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
namespace Kauth\Token;
4+
5+
/**
6+
* @author @code4mk <hiremostafa@gmail.com>
7+
* @author @0devco <with@0dev.co>
8+
* @since 2019
9+
* @copyright 0dev.co (https://0dev.co)
10+
*/
11+
12+
use \Firebase\JWT\JWT;
13+
use Illuminate\Http\Request;
14+
use DateTime;
15+
use DateInterval;
16+
use Config;
17+
use Cookie;
18+
19+
class Token
20+
{
21+
public function create($tokenID,$userType){
22+
$issueDate = new DateTime();
23+
$expiredDate = new DateTime();
24+
$tokenDuration = Config::get('kauth.token_exp') ? Config::get('kauth.token_exp') : 'P32D';
25+
$jwtIss = Config::get('kauth.payload.iss') ? Config::get('kauth.payload.iss') : 'https://code4mk.org';
26+
$jwtAud = Config::get('kauth.payload.aud') ? Config::get('kauth.payload.aud') : 'https://code4mk.org';
27+
$expiredDate->add(new DateInterval($tokenDuration));
28+
$key = "example_key";
29+
$token = array(
30+
"iss" => $jwtIss,
31+
"ut" => $userType,
32+
"iat" => $issueDate->getTimestamp(),
33+
"expM" => $expiredDate->getTimestamp(),
34+
"tid" => $tokenID,
35+
);
36+
$jwt = JWT::encode($token,$key);
37+
38+
return $jwt;
39+
}
40+
41+
public function tokon(){
42+
$token_header = Config::get('kauth.token_header_name') ? Config::get('kauth.token_header_name') : 'tokon';
43+
$tokon = \Request::header($token_header);
44+
45+
if($tokon === null && (Config::get('kauth.cookie_auth')) ){
46+
try {
47+
//return $_COOKIE['kauth_token'];
48+
return $_COOKIE['authtoken'];
49+
} catch (\Exception $e) {
50+
return $e;
51+
}
52+
53+
54+
}
55+
return $tokon;
56+
}
57+
58+
public function payload(){
59+
$key = "example_key";
60+
$tokon = $this->tokon();
61+
$jwt = JWT::decode($tokon, $key, array('HS256'));
62+
$payload = (array) $jwt;
63+
return $payload;
64+
}
65+
66+
public function payloader($tokon){
67+
$key = "example_key";
68+
$jwt = JWT::decode($tokon, $key, array('HS256'));
69+
$payload = (array) $jwt;
70+
return $payload;
71+
}
72+
73+
public function isExpired(){
74+
try {
75+
$instanceTime = new DateTime();
76+
if($instanceTime->getTimestamp() > $this->payload()["expM"] ){
77+
return true;
78+
}
79+
return false;
80+
} catch (\Exception $e) {
81+
return "jwt token is error";
82+
}
83+
}
84+
}

‎test/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)
Please sign in to comment.