ikechukwukalu / sanctumauthstarter
Laravel sanctum auth starter
Installs: 1 691
Dependents: 0
Suggesters: 0
Security: 0
Stars: 12
Watchers: 1
Forks: 2
Open Issues: 2
pkg:composer/ikechukwukalu/sanctumauthstarter
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 bootstrapnpm install --save-dev laravel-echo pusher-js- Uncomment
use Illuminate\Contracts\Auth\MustVerifyEmail;inUsermodel class - Add
two_factorcolumns to thefillableandhiddenarrays within theUsermodel class. At the end theUsershould 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:controllersphp artisan sas:routesphp artisan sas:tests
PUBLISH MIGRATIONS AND CONFIG
php artisan vendor:publish --tag=sas-migrationsphp 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=predisandBROADCAST_DRIVER=pusherwithin your.envfile. - Your
laravel-echoconfig 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=rediswithin your.envfile. - Uncomment
App\Providers\BroadcastServiceProvider::classinconfig\app.php - Your
.envshould 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
virtualhostSSL 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:serveandphp artisan queue:work php artisan servenpm 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/socialiteto view a sample Google sign-up/sign-in page to view the generatedaccess_tokenafter 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.phpand 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.phpwith 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-factorto 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-factorto 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-factorto disable 2fa,api/current-recovery-codesto retrieve current recovery codes andapi/new-recovery-codesto 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/scribephp artisan vendor:publish --tag=scribe-config- Change
'prefixes' => ['api/*']to'prefixes' => ['*']if you want to see the docs for APIs for theweb.phpas well. php artisan scribe:generate
Visit your newly generated docs:
- If you're using
statictype, find thedocs/index.htmlfile in yourpublic/folder and open it in your browser. - If you're using
laraveltype, 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.