├── LICENSE ├── README.md ├── composer.json └── src ├── Http └── Controllers │ └── Auth │ ├── ForgotPasswordController.php │ ├── LoginController.php │ ├── RegisterController.php │ └── ResetPasswordController.php ├── LaravelAPIAuthServiceProvider.php ├── Models ├── PasswordReset.php └── User.php ├── Notifications ├── PasswordResetRequest.php └── PasswordResetSuccess.php ├── config └── apiauth.php ├── database └── migrations │ ├── 2014_10_12_000000_create_users_table.php │ └── 2020_04_07_091043_create_password_resets_table.php └── routes └── api.php /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Abdulfatai Suleiman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel API Auth 2 | 3 | [![GitHub issues](https://img.shields.io/github/issues/iamnotstatic/laravel-api-auth)](https://github.com/iamnotstatic/laravel-api-auth/issues) 4 | [![GitHub stars](https://img.shields.io/github/stars/iamnotstatic/laravel-api-auth)](https://github.com/iamnotstatic/laravel-api-auth/stargazers) 5 | [![GitHub license](https://img.shields.io/github/license/iamnotstatic/laravel-api-auth)](https://github.com/iamnotstatic/laravel-api-auth) 6 | [![Total Downloads](https://img.shields.io/packagist/dt/iamnotstatic/laravel-api-auth)](https://github.com/iamnotstatic/laravel-api-auth) 7 | 8 | ## Introduction 9 | 10 | > A Laravel Package for easy API authentication setup with passport 11 | 12 | ## Installation 13 | 14 | To get the latest version of Laravel Api Auth, simply require it 15 | 16 | ```bash 17 | composer require iamnotstatic/laravel-api-auth 18 | ``` 19 | 20 | ## Configuration 21 | 22 | You can publish the configuration file using this command: 23 | 24 | ```bash 25 | php artisan vendor:publish --provider="Iamnotstatic\LaravelAPIAuth\LaravelAPIAuthServiceProvider" 26 | ``` 27 | 28 | Migrate your database after installing the package 29 | 30 | ```bash 31 | php artisan migrate 32 | ``` 33 | 34 | This command will create the encryption keys needed to generate secure access tokens. In addition, the command will create "personal access" and "password grant" clients which will be used to generate access tokens 35 | 36 | ```bash 37 | php artisan passport:install 38 | ``` 39 | 40 | Next, you should call the Passport::routes method within the boot method of your AuthServiceProvider. This method will register the routes necessary to issue access tokens and revoke access tokens, clients, and personal access tokens: 41 | 42 | ```php 43 | 'App\Policies\ModelPolicy', 60 | ]; 61 | 62 | /** 63 | * Register any authentication / authorization services. 64 | * 65 | * @return void 66 | */ 67 | public function boot() 68 | { 69 | $this->registerPolicies(); 70 | 71 | Passport::routes(); 72 | } 73 | } 74 | ``` 75 | 76 | In your config/auth.php configuration file, you should set the driver option of the api authentication guard to passport. This will instruct your application to use Passport's TokenGuard when authenticating incoming API requests: 77 | 78 | ```php 79 | 'guards' => [ 80 | 'web' => [ 81 | 'driver' => 'session', 82 | 'provider' => 'users', 83 | ], 84 | 85 | 'api' => [ 86 | 'driver' => 'passport', 87 | 'provider' => 'users', 88 | ], 89 | ], 90 | ``` 91 | 92 | In your config/auth.php configuration file, you should set the model option of the package model. This will provide a few helper methods to allow you to inspect the authenticated user's token and scopes: 93 | 94 | ```php 95 | 'providers' => [ 96 | 'users' => [ 97 | 'driver' => 'eloquent', 98 | 'model' => Iamnotstatic\LaravelAPIAuth\Models\User::class, 99 | ], 100 | 101 | // 'users' => [ 102 | // 'driver' => 'database', 103 | // 'table' => 'users', 104 | // ], 105 | ], 106 | ``` 107 | 108 | ## Usage 109 | 110 | Now, we can simple test by rest client tools (Postman), So I test it and you can see below screenshots. 111 | 112 | > In this api you have to set two header as listed below: 113 | 114 | ```bash 115 | Accept: application/json 116 | ``` 117 | 118 | ![pkg imgs](https://user-images.githubusercontent.com/46509072/78991850-d1b2ee80-7b31-11ea-8c90-e588fe7789ab.png) 119 | 120 | Register 121 | 122 | ![register](https://user-images.githubusercontent.com/46509072/78993042-bc8b8f00-7b34-11ea-8eb4-449c7f82fd3f.png) 123 | 124 | Login 125 | 126 | ![login](https://user-images.githubusercontent.com/46509072/78993086-d3ca7c80-7b34-11ea-807f-8bbf7baa00e8.png) 127 | 128 | Logout 129 | 130 | ![logout](https://user-images.githubusercontent.com/46509072/78993159-f8beef80-7b34-11ea-9f0e-bff2dda268d8.png) 131 | 132 | Get User 133 | 134 | ![getuser](https://user-images.githubusercontent.com/46509072/78993121-e93fa680-7b34-11ea-98da-6ff837f52b78.png) 135 | 136 | Forgotten Password 137 | 138 | ![forgottenpass](https://user-images.githubusercontent.com/46509072/78993185-0d02ec80-7b35-11ea-888b-d1ff379170c8.png) 139 | 140 | Reset Passowrd 141 | 142 | ![passwordreset](https://user-images.githubusercontent.com/46509072/78993214-1e4bf900-7b35-11ea-9c2b-346e1f555b97.png) 143 | 144 | ## Contributing 145 | 146 | Please feel free to fork this package and contribute by submitting a pull request to enhance the functionalities. 147 | 148 | ## How can I thank you? 149 | 150 | Why not star the github repo? I'd love the attention! Why not share the link for this repository on Twitter or HackerNews? Spread the word! 151 | 152 | Don't forget to [follow me on twitter](https://twitter.com/iamnotstatic)! 153 | 154 | Thanks! 155 | Abdulfatai Suleiman. 156 | 157 | ## License 158 | 159 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 160 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iamnotstatic/laravel-api-auth", 3 | "description": "A Laravel Package for easy API authentication setup with passport", 4 | "keywords": [ 5 | "laravel", 6 | "passport", 7 | "oauth" 8 | ], 9 | "require": { 10 | "guzzlehttp/guzzle": "^6.3", 11 | "laravel/passport": "^8.4" 12 | }, 13 | "license": "MIT", 14 | "authors": [ 15 | { 16 | "name": "iamnotstatic", 17 | "email": "staticdev20046@gmail.com" 18 | } 19 | ], 20 | "minimum-stability": "dev", 21 | "autoload": { 22 | "psr-4": { 23 | "Iamnotstatic\\LaravelAPIAuth\\": "src" 24 | } 25 | }, 26 | "extra": { 27 | "laravel": { 28 | "providers": [ 29 | "Iamnotstatic\\LaravelAPIAuth\\LaravelAPIAuthServiceProvider" 30 | ] 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Http/Controllers/Auth/ForgotPasswordController.php: -------------------------------------------------------------------------------- 1 | all(), [ 36 | 'email' => 'required|string|email' 37 | ]); 38 | 39 | if ($validator->fails()) { 40 | return response()->json(['error' => $validator->errors()], 400); 41 | } 42 | 43 | $user = User::where('email', $request->email)->first(); 44 | 45 | if (!$user) { 46 | return response()->json(['error' => 'We can\'t find a user with that e-mail address.'], 400); 47 | } 48 | 49 | $passwordReset = PasswordReset::updateOrCreate( 50 | [ 51 | 'email' => $user->email 52 | ], 53 | [ 54 | 'email' => $user->email, 55 | 'token' => Str::random(60) 56 | ] 57 | ); 58 | 59 | if ($user && $passwordReset) 60 | try { 61 | $user->notify( 62 | new PasswordResetRequest($passwordReset->token) 63 | ); 64 | } catch (\Throwable $th) { 65 | throw $th; 66 | } 67 | 68 | return response()->json(['success' => 'We have e-mailed your password reset link!']); 69 | 70 | } 71 | 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/Http/Controllers/Auth/LoginController.php: -------------------------------------------------------------------------------- 1 | all(), [ 25 | 'email' => 'required|string|email', 26 | 'password' => 'required|string' 27 | ]); 28 | 29 | if ($validator->fails()) { 30 | return response()->json(['error' => $validator->errors()], 400); 31 | } 32 | 33 | if (Auth::attempt(['email' => $request->email, 'password' => $request->password])) { 34 | $user = Auth::user(); 35 | $success['token'] = $user->createToken('Personal Access Token')-> accessToken; 36 | return response()->json([ 37 | 'success' => $success, 38 | 'token_type' => 'Bearer' 39 | ], 200); 40 | } else { 41 | return response()->json(['error' => 'Invalid Credentails'], 401); 42 | } 43 | } 44 | 45 | /** 46 | * details api 47 | * 48 | * @return \Illuminate\Http\Response 49 | */ 50 | public function getUser() 51 | { 52 | $user = Auth::user(); 53 | return response()->json(['success' => $user], 200); 54 | } 55 | 56 | 57 | /** 58 | * Logout user (Revoke the token) 59 | * 60 | * @return [string] message 61 | */ 62 | public function logout(Request $request) 63 | { 64 | $request->user()->token()->revoke(); 65 | return response()->json([ 66 | 'message' => 'Successfully logged out' 67 | ]); 68 | } 69 | } -------------------------------------------------------------------------------- /src/Http/Controllers/Auth/RegisterController.php: -------------------------------------------------------------------------------- 1 | all(), [ 27 | 'name' => 'required|string|max:255', 28 | 'email' => 'required|string|email|max:255|unique:users', 29 | 'password' => 'required|string|min:8|confirmed' 30 | ]); 31 | 32 | if ($validator->fails()) { 33 | return response()->json(['error' => $validator->errors()], 400); 34 | } 35 | 36 | $user = new User; 37 | $user->name = $request->name; 38 | $user->email = $request->email; 39 | $user->password = bcrypt($request->password); 40 | $user->save(); 41 | $success['token'] = $user->createToken('Personal Access Token')-> accessToken; 42 | 43 | return response()->json([ 44 | 'success' => $success, 45 | 'token_type' => 'Bearer' 46 | ], 201); 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/Http/Controllers/Auth/ResetPasswordController.php: -------------------------------------------------------------------------------- 1 | first(); 36 | 37 | if (!$passwordReset) 38 | return response()->json([ 'error' => 'This password reset token is invalid.'], 404); 39 | 40 | if (Carbon::parse($passwordReset->updated_at)->addMinutes(720)->isPast()) { 41 | $passwordReset->delete(); 42 | return response()->json([ 'error' => 'This password reset token is invalid.'], 404); 43 | } 44 | 45 | return response()->json($passwordReset); 46 | 47 | } 48 | 49 | 50 | /** 51 | * Reset password 52 | * 53 | * @param [string] email 54 | * @param [string] password 55 | * @param [string] password_confirmation 56 | * @param [string] token 57 | * @return [string] message 58 | * @return [json] user object 59 | */ 60 | public function reset(Request $request) 61 | { 62 | $validate = Validator::make($request->all(), [ 63 | 'email' => 'required|string|email', 64 | 'password' => 'required|string|min:8|confirmed', 65 | 'token' => 'required|string' 66 | ]); 67 | 68 | if ($validate->fails()) { 69 | return response()->json(['error' => $validate->errors()], 400); 70 | } 71 | 72 | $passwordReset = PasswordReset::where([ 73 | ['token', $request->token], 74 | ['email', $request->email] 75 | ])->first(); 76 | 77 | if (!$passwordReset) 78 | return response()->json([ "error" => "This password reset token is invalid."], 404); 79 | 80 | $user = User::where('email', $passwordReset->email)->first(); 81 | 82 | if (!$user) 83 | return response()->json(["error" => "We can't find a user with that e-mail address."], 404); 84 | 85 | $user->password = bcrypt($request->password); 86 | $user->save(); 87 | $passwordReset->delete(); 88 | 89 | try { 90 | $user->notify(new PasswordResetSuccess($passwordReset)); 91 | } catch (\Throwable $th) { 92 | //throw $th; 93 | } 94 | 95 | return response()->json(['success' => 'Password was reset successfully you can now login']); 96 | } 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/LaravelAPIAuthServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadRoutesFrom(__DIR__. '/routes/api.php'); 27 | $this->loadViewsFrom(__DIR__. '/view', 'apiauth'); 28 | $this->loadMigrationsFrom(__DIR__.'/database/migrations'); 29 | $this->mergeConfigFrom( 30 | __DIR__.'/config/apiauth.php', 'apiauth' 31 | ); 32 | $this->publishes([ 33 | __DIR__.'/Models' => app_path('Models'), 34 | __DIR__.'/Http/Controllers/Auth' => app_path('Http/Controllers/Auth') 35 | ]); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Models/PasswordReset.php: -------------------------------------------------------------------------------- 1 | 'datetime', 40 | ]; 41 | 42 | public static function generateVerificationCode() { 43 | return Str::random(25); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/Notifications/PasswordResetRequest.php: -------------------------------------------------------------------------------- 1 | token = $token; 24 | } 25 | 26 | /** 27 | * Get the notification's delivery channels. 28 | * 29 | * @param mixed $notifiable 30 | * @return array 31 | */ 32 | public function via($notifiable) 33 | { 34 | return ['mail']; 35 | } 36 | 37 | /** 38 | * Get the mail representation of the notification. 39 | * 40 | * @param mixed $notifiable 41 | * @return \Illuminate\Notifications\Messages\MailMessage 42 | */ 43 | public function toMail($notifiable) 44 | { 45 | $url = url('/api/password/find/'.$this->token); 46 | return (new MailMessage) 47 | ->line('You are receiving this email because we received a password reset request for your account.') 48 | ->action('Reset Password', url($url)) 49 | ->line('If you did not request a password reset, no further action is required.'); 50 | } 51 | 52 | /** 53 | * Get the array representation of the notification. 54 | * 55 | * @param mixed $notifiable 56 | * @return array 57 | */ 58 | public function toArray($notifiable) 59 | { 60 | return [ 61 | // 62 | ]; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Notifications/PasswordResetSuccess.php: -------------------------------------------------------------------------------- 1 | line('You have changed your password successful.') 45 | ->line('If you did change password, no further action is required.') 46 | ->line('If you did not change password, protect your account.'); 47 | } 48 | 49 | /** 50 | * Get the array representation of the notification. 51 | * 52 | * @param mixed $notifiable 53 | * @return array 54 | */ 55 | public function toArray($notifiable) 56 | { 57 | return [ 58 | // 59 | ]; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/config/apiauth.php: -------------------------------------------------------------------------------- 1 | 'LaravelApiAuth' 5 | ]; -------------------------------------------------------------------------------- /src/database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('name'); 19 | $table->string('email')->unique(); 20 | $table->timestamp('email_verified_at')->nullable(); 21 | $table->string('password'); 22 | $table->rememberToken(); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('users'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/database/migrations/2020_04_07_091043_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('email')->index(); 19 | $table->string('token'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('password_resets'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/routes/api.php: -------------------------------------------------------------------------------- 1 | 'Iamnotstatic\LaravelAPIAuth\Http\Controllers'], function() { 18 | 19 | Route::group(['prefix' => 'api'], function() { 20 | 21 | Route::post('register', 'Auth\RegisterController@register')->name('register'); 22 | Route::post('login', 'Auth\LoginController@login')->name('login'); 23 | 24 | Route::group(['middleware' => 'auth:api'], function() { 25 | Route::get('/logout', 'Auth\LoginController@logout')->name('logout'); 26 | Route::get('/getuser', 'Auth\LoginController@getUser')->name('getuser'); 27 | }); 28 | 29 | Route::post('password/forgotten', 'Auth\ForgotPasswordController@forgotten'); 30 | Route::get('password/find/{token}', 'Auth\ResetPasswordController@find'); 31 | Route::post('password/reset', 'Auth\ResetPasswordController@reset'); 32 | 33 | }); 34 | 35 | }); 36 | 37 | --------------------------------------------------------------------------------