├── 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 | ![kauth](https://user-images.githubusercontent.com/17185462/52489899-aa8b2500-2bed-11e9-8092-9b44bb827d17.png) 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 --------------------------------------------------------------------------------