├── README.md
├── composer.json
├── config
└── kauth.php
├── migrations
└── 2019_02_04_082555_create_kauth_table.php
├── src
├── Auth
│ └── Auth.php
├── Facades
│ └── Auth.php
├── KauthServiceProvider.php
├── Model
│ └── KauthModel.php
└── Token
│ └── Token.php
└── test
└── .gitkeep
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # `kauth`
4 | kauth is JWT API Authentication ( jwt-auth ) for laravel
5 |
6 |
7 | # Installation
8 | you can install kauth package by command
9 | ```bash
10 | composer require code4mk/kauth
11 | ```
12 | # Setup
13 |
14 | ### 1) Vendor publish.
15 |
16 | ```bash
17 | php artisan vendor:publish --provider="Kauth\KauthServiceProvider" --tag=config
18 | php artisan vendor:publish --provider="Kauth\KauthServiceProvider" --tag=migations
19 | ```
20 | ### 2) Config setup
21 |
22 | * `config\kauth.php`
23 |
24 | * set `token_header_name` that you can use with guzzle or axios header
25 | * default `token_header_name` name is `tokon`
26 |
27 | # Usage
28 |
29 | ## `Kauth::attempt()` functions
30 |
31 | * guard('name')
32 | ```php
33 | // guard name will be user table name
34 | Kauth::guard("users")
35 | ```
36 | * socialite()->attempt()
37 | ```php
38 | // laravel socialite system
39 | // credential will be only email
40 | Kauth::guard("users")->socialite()
41 | ->attempt(["email"=>"ex@gmail.com"]);
42 | ```
43 | * normal attempt()
44 | ```php
45 | // your all desired credentials
46 | // password credentail need
47 | Kauth::guard("users")
48 | ->attempt(["email"=>"ex@email.com","password"=>1234])
49 | ```
50 |
51 | ~ `attempt() return a jwt token` which you pass with request header (ex:axios header)
52 | ## attempt special
53 |
54 | * username credential will be optional as (id|email|username) . (ex: facebook username)
55 | * `usernames` describe which columns you want to match for username
56 |
57 | ```php
58 | attempt(["usernames"=>["id","email","name"],"username"=>"request query for username","password=>123456"]);
59 | ```
60 | ## Kauth::check()
61 |
62 | ```php
63 | Kauth::check();
64 | ```
65 | ## Kauth::id()
66 |
67 | ```php
68 | Kauth::id();
69 | ```
70 |
71 | ## Kauth::refreshToken()
72 |
73 | ```php
74 | Kauth::refreshToken()
75 | ```
76 |
77 | ## Kauth::logout()
78 |
79 | ```php
80 | Kauth::logout();
81 | ```
82 |
83 | ## Kauth::logoutOtherDevices()
84 |
85 | ```php
86 | Kauth::logoutOtherDevices();
87 | ```
88 |
89 | 
90 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
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 | }
45 |
--------------------------------------------------------------------------------
/config/kauth.php:
--------------------------------------------------------------------------------
1 | "",
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 | ];
69 |
--------------------------------------------------------------------------------
/migrations/2019_02_04_082555_create_kauth_table.php:
--------------------------------------------------------------------------------
1 | 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 | }
44 |
--------------------------------------------------------------------------------
/src/Auth/Auth.php:
--------------------------------------------------------------------------------
1 |
7 | * @author @0devco
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 |
21 | class Auth
22 | {
23 |
24 | protected $guard;
25 |
26 | protected $socialite;
27 |
28 | protected $user_type = '';
29 |
30 | public function __construct()
31 | {
32 | $this->guard();
33 | $this->socialite(false);
34 | }
35 |
36 |
37 | /**
38 | *
39 | * set gaurd name
40 | *
41 | *@return string guard
42 | */
43 | public function guard($guard ='users')
44 | {
45 | $this->guard = $guard;
46 | return $this;
47 | }
48 |
49 | /**
50 | *
51 | * socialite system
52 | *
53 | *@return boolean
54 | */
55 | public function socialite($status = true)
56 | {
57 | $this->socialite = $status;
58 | return $this;
59 | }
60 |
61 |
62 | /**
63 | *
64 | * attempt credentials
65 | *
66 | *@return string jwt
67 | */
68 | public function attempt($credentials)
69 | {
70 | $credential = [];
71 | $getTokennames = $credentials['usernames'] ?? [];
72 | $getTokenname = $credentials['username'] ?? '';
73 |
74 | // store credentials without password & username
75 |
76 | foreach ($credentials as $key => $value){
77 | if($key === 'password' || !empty($key === 'usernames') || !empty($key === 'username')){
78 | // nothing
79 | } else {
80 | $credential[$key] = $value;
81 | }
82 | }
83 |
84 | // fetch user by credentials
85 |
86 | $getToken = DB::table(Config::get('kauth.guard.' . $this->guard . '.table'))
87 | // multiple username accept (id||username||email >> etc)
88 | ->where(function ($query) use ($getTokennames,$getTokenname){
89 | foreach ($getTokennames as $key => $value) {
90 | $query->orWhere($value,$getTokenname)
91 | ->orWhere($value,$getTokenname);
92 | }
93 | })
94 | ->where(function ($query) use ($credential) {
95 | foreach ($credential as $key => $value) {
96 | $query->where($key,$value);
97 | }
98 | })
99 | ->first();
100 |
101 | // check has user and socialite
102 |
103 | if(!empty($getToken) && !($this->socialite)){
104 | $getTokenPassword = Hash::check($credentials['password'],$getToken->password);
105 | } elseif (!empty($getToken) && $this->socialite) {
106 | $getTokenPassword = true;
107 | } else {
108 | $getTokenPassword = false;
109 | }
110 |
111 | // check user and password then store jwt token
112 |
113 | if (!empty($getToken) && $getTokenPassword ) {
114 | $jwt = new KauthModel;
115 | $jwt->user_id = $getToken->id;
116 | $jwt->browser = \Request::get('browser');
117 | $jwt->os = \Request::get('os');
118 | $jwt->device = \Request::get('device');
119 | $jwt->ip = \Request::get('ip');
120 | $jwt->active = true;
121 | $jwt->guard = $this->guard;
122 | $jwt->save();
123 |
124 | $secret = new Token();
125 | if (Schema::hasColumn(Config::get('kauth.guard.' . $this->guard . '.table'), 'user_type')) {
126 | $this->user_type = $getToken->user_type;
127 | }
128 | $tokon = $secret->create($jwt->id,$this->user_type);
129 | $payloader = $secret->payloader($tokon);
130 | $jwt->tokon = $tokon;
131 | $jwt->iat = $payloader['iat'];
132 | $jwt->exp = $payloader['expM'];
133 |
134 | if (Schema::hasColumn($this->guard, 'user_type')) {
135 | $jwt->user_type = $getToken->user_type;
136 | }
137 | $jwt->save();
138 | return $jwt->tokon;
139 | }
140 | return "wrong credentials";
141 | }
142 |
143 | /**
144 | *
145 | * auth check
146 | *
147 | *@return boolean
148 | */
149 | public function check()
150 | {
151 | try {
152 | $token = new Token();
153 | $getToken = KauthModel::where('tokon',$token->tokon())->first();
154 | $instanceTime = new DateTime();
155 | if(!empty($getToken) && ($instanceTime->getTimestamp() <= $getToken->exp)){
156 | return true;
157 | }
158 | return false;
159 | } catch (\Exception $e) {
160 | return "jwt-error";
161 | }
162 |
163 | }
164 |
165 | /**
166 | *
167 | * auth user id
168 | *
169 | *@return integer id
170 | */
171 | public function id()
172 | {
173 | try {
174 | $token = new Token();
175 | $getToken = KauthModel::where('tokon',$token->tokon())->first();
176 | $instanceTime = new DateTime();
177 | if(!empty($getToken) && ($instanceTime->getTimestamp() <= $getToken->exp)){
178 | return $getToken->user_id;
179 | }
180 | return 0;
181 | } catch (\Exception $e) {
182 | return "jwt-error";
183 | }
184 |
185 | }
186 |
187 | public function auths()
188 | {
189 | $auths = KauthModel::where('user_id',$this->id())
190 | ->orderBy('id','desc')
191 | ->get();
192 | return $auths;
193 | }
194 |
195 | /**
196 | *
197 | * auth logout
198 | *
199 | * delete auth credentials
200 | */
201 | public function logout()
202 | {
203 | try {
204 | $token = new Token();
205 | $getToken = KauthModel::where('tokon',$token->tokon())->first();
206 | $getToken->delete();
207 | } catch (\Exception $e) {
208 | return "jwt-error";
209 | }
210 |
211 |
212 | }
213 |
214 | /**
215 | *
216 | * logout all devices
217 | *
218 | * delete auth user's all token
219 | * without current token id
220 | */
221 | public function logoutOtherDevices()
222 | {
223 | try {
224 | $token = new Token();
225 | $getToken = KauthModel::where('tokon',$token->tokon())->first();
226 |
227 | // fetch all token without current token
228 |
229 | KauthModel::where('user_id',$getToken->user_id)
230 | -> where(function ($query) use ($getToken){
231 | $query->whereNotIn('id',[$getToken->id]);
232 | })
233 | ->delete();
234 | } catch (\Exception $e) {
235 | return "jwt-error";
236 | }
237 |
238 | }
239 |
240 | /**
241 | *
242 | * refresh token
243 | *
244 | * edit existing token
245 | *
246 | */
247 | public function refreshToken()
248 | {
249 | try {
250 | $token = new Token();
251 | $getToken = KauthModel::where('tokon',$token->tokon())->first();
252 | $getToken->tokon = $token->create($getToken->id);
253 | $payloader = $token->payloader($token->create($getToken->id));
254 | $getToken->iat = $payloader['iat'];
255 | $getToken->exp = $payloader['expM'];
256 | $getToken->save();
257 | return $getToken->tokon;
258 | } catch (\Exception $e) {
259 | return "jwt-error";
260 | }
261 | }
262 | }
263 |
--------------------------------------------------------------------------------
/src/Facades/Auth.php:
--------------------------------------------------------------------------------
1 |
7 | * @author @0devco
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 | }
26 |
--------------------------------------------------------------------------------
/src/KauthServiceProvider.php:
--------------------------------------------------------------------------------
1 |
7 | * @author @0devco
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 | }
49 |
--------------------------------------------------------------------------------
/src/Model/KauthModel.php:
--------------------------------------------------------------------------------
1 |
7 | * @author @0devco
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 | }
23 |
--------------------------------------------------------------------------------
/src/Token/Token.php:
--------------------------------------------------------------------------------
1 |
7 | * @author @0devco
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 | } catch (\Exception $e) {
49 | return $e;
50 | }
51 |
52 |
53 | }
54 | return $tokon;
55 | }
56 |
57 | public function payload(){
58 | $key = "example_key";
59 | $tokon = $this->tokon();
60 | $jwt = JWT::decode($tokon, $key, array('HS256'));
61 | $payload = (array) $jwt;
62 | return $payload;
63 | }
64 |
65 | public function payloader($tokon){
66 | $key = "example_key";
67 | $jwt = JWT::decode($tokon, $key, array('HS256'));
68 | $payload = (array) $jwt;
69 | return $payload;
70 | }
71 |
72 | public function isExpired(){
73 | try {
74 | $instanceTime = new DateTime();
75 | if($instanceTime->getTimestamp() > $this->payload()["expM"] ){
76 | return true;
77 | }
78 | return false;
79 | } catch (\Exception $e) {
80 | return "jwt token is error";
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/test/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/code4mk/kauth/ae014f739409dfd58855d5ff600488091c642c9a/test/.gitkeep
--------------------------------------------------------------------------------