ikechukwukalu / sanctumauthstarter
Laravel sanctum auth starter
Installs: 1 310
Dependents: 0
Suggesters: 0
Security: 0
Stars: 12
Watchers: 1
Forks: 2
Open Issues: 2
Requires
- php: ^8.0
- beyondcode/laravel-websockets: ^1.14
- doctrine/dbal: ^3.5
- hisorange/browser-detect: ^4.5
- illuminate/auth: ^9.0|^10.0
- illuminate/broadcasting: ^9.0|^10.0
- illuminate/bus: ^9.0|^10.0
- illuminate/contracts: ^9.0|^10.0
- illuminate/database: ^9.0|^10.0
- illuminate/events: ^9.0|^10.0
- illuminate/http: ^9.0|^10.0
- illuminate/notifications: ^9.0|^10.0
- illuminate/queue: ^9.0|^10.0
- illuminate/routing: ^9.0|^10.0
- illuminate/support: ^9.0|^10.0
- illuminate/validation: ^9.0|^10.0
- illuminate/view: ^9.0|^10.0
- laragear/two-factor: ^1.2
- laravel/sanctum: ^3.0
- laravel/socialite: ^5.5
- laravel/ui: ^4.0
- nesbot/carbon: ^2.67
- predis/predis: ^2.1
- pusher/pusher-php-server: ^7.2
- stevebauman/location: ^6.6
- symfony/console: ^6.0
- symfony/finder: ^6.0
Requires (Dev)
- knuckleswtf/scribe: dev-master
- mockery/mockery: ^1.4.4
- orchestra/testbench: ^7.0|^8.0
- php-parallel-lint/php-parallel-lint: dev-develop
- phpunit/phpunit: ^9.0|^10.0
README
This is a very flexible and customisable laravel package (boilerplate) that utilises laravel/ui and laravel-sanctum to create Basic Authetication classes and other helpful functionalities to give you a quick start when building REST APIs using Laravel. The following functionalities are made available:
- User registration
- User login
- Auto login after registration
- Login throttling
- Login 2FA
- Social media login
- Forgot password
- Email verification
- Resend email verification
- Reset password
- Change password
- Edit user profile
- Notifications
- Welcome notification
- Email verification
- Login notification
- Password change notification
- Generate documentation
- Helper CI/CD files for GitHub
REQUIREMENTS
- PHP 8+
- Laravel 9+
STEPS TO INSTALL
composer require ikechukwukalu/sanctumauthstarter
php artisan ui bootstrap
npm install --save-dev laravel-echo pusher-js
- Uncomment
use Illuminate\Contracts\Auth\MustVerifyEmail;
inUser
model class - Add
two_factor
columns to thefillable
andhidden
arrays within theUser
model class. At the end theUser
should look similar to this:
use Laravel\Sanctum\HasApiTokens; use Laragear\TwoFactor\TwoFactorAuthentication; use Laragear\TwoFactor\Contracts\TwoFactorAuthenticatable; class User extends Authenticatable implements TwoFactorAuthenticatable, MustVerifyEmail { use HasApiTokens, HasFactory, Notifiable, TwoFactorAuthentication; /** * The attributes that are mass assignable. * * @var array<int, string> */ protected $fillable = [ 'name', 'email', 'password', 'two_factor', 'socialite_signup', 'form_signup' ]; /** * The attributes that should be hidden for serialization. * * @var array<int, string> */ protected $hidden = [ 'password', 'remember_token', 'two_factor', ]; /** * The attributes that should be cast. * * @var array<string, string> */ protected $casts = [ 'email_verified_at' => 'datetime', ]; }
GENERATE AUTH CONTROLLERS, REQUESTS, SERVICES AND ROUTES
You can run php artisan sas:setup
to generate them at once. You can also call generate them separately:
php artisan sas:controllers
php artisan sas:routes
php artisan sas:tests
PUBLISH MIGRATIONS AND CONFIG
php artisan vendor:publish --tag=sas-migrations
php artisan vendor:publish --tag=sas-config
WEBSOCKETS AND QUEUES
This package utilizes laravel beyondcode/laravel-websockets to pass access_token
to the client after authentication. First, you must setup your laravel app for broadcasts. In order to do that run the following:
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
- Set
REDIS_CLIENT=predis
andBROADCAST_DRIVER=pusher
within your.env
file. - Your
laravel-echo
config should look similar to this:
window.Echo = new Echo({ broadcaster: 'pusher', key: import.meta.env.VITE_PUSHER_APP_KEY, wsHost: window.location.hostname, wsPort: 6001, forceTLS: false, encrypted: false, enabledTransports: ['ws', 'wss'], disableStats: true, cluster:import.meta.env.VITE_PUSHER_APP_CLUSTER, authorizer: (channel, options) => { return { authorize: (socketId, callback) => { axios.post('/broadcasting/auth', { socket_id: socketId, channel_name: channel.name }) .then(response => { callback(false, response.data); }) .catch(error => { callback(true, error); }); } }; }, });
You will need a queue worker for the notifications and other events.
- Set
QUEUE_CONNECTION=redis
within your.env
file. - Uncomment
App\Providers\BroadcastServiceProvider::class
inconfig\app.php
- Your
.env
should look similar to this
PUSHER_APP_KEY=app-key PUSHER_APP_ID=app-id PUSHER_APP_SECRET=app-secret PUSHER_HOST=127.0.0.1 PUSHER_PORT=6001 PUSHER_SCHEME=http PUSHER_APP_CLUSTER=mt1
- For SSL using apache. The snippet below should be placed within the
virtualhost
SSL config.
ProxyPass "/app/" "ws://127.0.0.1:6001/app/" ProxyPass "/app/" "http://127.0.0.1:6001/app/"
- Run
php artisan config:clear
,php artisan migrate
,php artisan websockets:serve
andphp artisan queue:work
php artisan serve
npm install && npm run dev
WEBVIEW LOGINS
- Social media login
- Two-factor login
Social Media Login
Add the following to your config/services.php
file.
'google' => [ 'client_id' => env('GOOGLE_CLIENT_ID'), 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 'redirect' => env('GOOGLE_CLIENT_REDIRECT'), ],
- Navigate to
auth/socialite
to view a sample Google sign-up/sign-in page to view the generatedaccess_token
after sign up. Uncomment the route within theweb.php
. Below is the script that is called within the viewresources/views/vendor/sanctumauthstarter/socialite/auth.blade.php
.
window.addEventListener('DOMContentLoaded', () => { const getUserUUID = () => { let userUUID = localStorage.getItem('user_uuid'); if (!userUUID) { userUUID = crypto.randomUUID(); localStorage.setItem('user_uuid', userUUID); } console.log('user_uuid created', userUUID); return userUUID; } const removeUserUUID = () => { if (localStorage.getItem('user_uuid')) { localStorage.removeItem('user_uuid'); } console.log('user_uuid removed'); } const USER_UUID = getUserUUID(); const TIMEOUT = parseInt("{{ $minutes }}") * 60 * 1000; window.Echo.channel(`access.token.socialite.${USER_UUID}`) .listen('.Ikechukwukalu\\Sanctumauthstarter\\Events\\SocialiteLogin', (e) => { console.log(`payload:`, e); }); document.getElementById('googleSignUp').onclick = () => { window.open( "{{ url('auth/redirect') }}/" + USER_UUID, '_blank' ) } setTimeout(() => { removeUserUUID(); }, TIMEOUT); });
- After a successful authentication, this view is displayed
resources/views/vendor/sanctumauthstarter/socialite/callback.blade.php
and it contains the following script:
window.addEventListener('DOMContentLoaded', () => { if (localStorage.getItem('user_uuid')) { localStorage.removeItem('user_uuid'); } });
Two-factor Login
This package utilizes Laragear/TwoFactor to power 2fa login and beyondcode/laravel-websockets to pass access_token
to the client after authentication.
2fa authentication has been implemented for both password login and social media login.
php artisan vendor:publish --provider="Laragear\TwoFactor\TwoFactorServiceProvider"
php artisan migrate
- Replace the form in
resources/views/vendor/two-factor/login.blade.php
with the code below:
<form method="get"> @php foreach ($_GET as $key => $value) { $key = htmlspecialchars($key); $value = htmlspecialchars($value); echo "<input type='hidden' name='$key' value='$value'/>"; } @endphp @csrf <p class="text-center"> {{ trans('two-factor::messages.continue') }} </p> <div class="form-row justify-content-center py-3"> @if($errors->isNotEmpty() || isset($message)) <div class="col-12 alert alert-danger pb-0"> <ul> @if (isset($message)) <li>{{ $message }}</li> @endif @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <div class="col-sm-8 col-8 mb-3"> <input type="text" name="{{ $input }}" id="{{ $input }}" class="@error($input) is-invalid @enderror form-control form-control-lg" minlength="6" placeholder="123456" required> </div> <div class="w-100"></div> <div class="col-auto mb-3"> <button type="submit" class="btn btn-primary btn-lg"> {{ trans('two-factor::messages.confirm') }} </button> </div> </div> </form>
- Call
api/create-two-factor
to create 2fa.
{ "status": "success", "status_code": 200, "data": { "qr_code": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg...", "uri": "otpauth://totp/%3Ajohndoe@xyz.com?label=johndoe%40xyz.com&secret=EQGRSNGAE3TREOT7XOLB5VVRS42LLXYS&algorithm=SHA1&digits=6", "string": "EQGRSNGAE3TREOT7XOLB5VVRS42LLXYS" } }
- Call
api/confirm-two-factor
to confirm 2fa and get recovery codes.
{ "status": "success", "status_code": 200, "data": { "message": "Download your recover codes and keep them safe!", "codes": [ { "code": "SV6OH71D", "used_at": null }, { "code": "62KEBSNE", "used_at": null }, { "code": "YSVHOG9X", "used_at": null }, ... ] } }
- Call
api/disable-two-factor
to disable 2fa,api/current-recovery-codes
to retrieve current recovery codes andapi/new-recovery-codes
to generate new recovery codes which replaces the previous batch.
Two factor enabled for password login
When 2fa has been enabled and a user attempts to login, a payload would be returned that contains a user_uuid
and a twofactor_url
.
{ "status": "success", "status_code": 200, "data": { "twofactor_url": "http://127.0.0.1:8000/twofactor/required/johndoe@xyz.com/0220dbe7-08dc-470e-b1e2-4411ba155bc1", "user_uuid": "0220dbe7-08dc-470e-b1e2-4411ba155bc1", "access_token": null, "message": "Two-Factor Authentication is required!" } }
The user_uuid
is used to create a laravel-echo
channel that would listen to a laravel broadcast. Navigate to auth/twofactor/{email}/{uuid}
to view the generated access_token
after uncommenting the route within the web.php
. This view resources/views/vendor/sanctumauthstarter/twofactor/auth.blade.php
contains a sample javascript
that works it out.
window.addEventListener('DOMContentLoaded', () => { const USER_UUID = "{{ Route::input('uuid') }}"; console.log(USER_UUID); window.Echo.channel(`access.token.twofactor.${USER_UUID}`) .listen('.Ikechukwukalu\\Sanctumauthstarter\\Events\\TwoFactorLogin', (e) => { console.log(`payload:`, e); }); });
Two factor enabled for social media login
When 2fa has been enabled a 2fa page will pop up over your browser.
DOCUMENTATION
To generate documentation:
composer require --dev knuckleswtf/scribe
php artisan vendor:publish --tag=scribe-config
- Change
'prefixes' => ['api/*']
to'prefixes' => ['*']
if you want to see the docs for APIs for theweb.php
as well. php artisan scribe:generate
Visit your newly generated docs:
- If you're using
static
type, find thedocs/index.html
file in yourpublic/
folder and open it in your browser. - If you're using
laravel
type, start your app (php artisan serve
), then visit/docs
.
example_languages
:
For each endpoint, an example request is shown in each of the languages specified in this array. Currently, only bash
(curl), javascript
(Fetch), php
(Guzzle) and python
(requests) are included. You can add extra languages, but you must also create the corresponding Blade view (see Adding more example languages).
Default: ["bash", "javascript"]
Please visit scribe for more details.
TESTS
It's recommended that you run the tests before you start adding your custom models and controllers.
Make sure to keep your database/factories/UserFactory.php
Class updated with your users
table so that the Tests can continue to run successfully.
Passwords
The passwords created within the database/factories/UserFactory.php
Class must match the validation below:
'password' => ['required', 'string', 'max:16', Password::min(8) ->letters()->mixedCase() ->numbers()->symbols() ->uncompromised(),
Running Tests
php artisan test
RECOMMENED PACKAGES
composer require ikechukwukalu/makeservice
composer require ikechukwukalu/databasebackup
composer require ikechukwukalu/requirepin
composer require ikechukwukalu/clamavfileupload
PUBLISH VIEWS
php artisan vendor:publish --tag=sas-views
PUBLISH LANG
php artisan vendor:publish --tag=sas-lang
PUBLISH LARAVEL EMAIL NOTIFICATIONS BLADE
php artisan vendor:publish --tag=laravel-notifications
PUBLISH GITHUB WORKFLOWS
php artisan vendor:publish --tag=github
LICENSE
The SAS package is an open-sourced software licensed under the MIT license.