tzm / authorizator
This is an easy to use, powerful and extendable Laravel package for authorization user actions via custom channels.
Requires
- php: ^7.2
- guzzlehttp/guzzle: ~6.0
README
This is an easy to use, tested, powerful and extendable Laravel package for the authorization of user actions via custom channels. It works by delivering an authorization code to the user (for e.g. via sms or e-mail) and then verifing it.
You can configure as many channels as you want. Each action can provide any channel configuration. Blade template and VUE component included.
Using this package you can define separate actions such as: two factor authorization, deleting account, authorizing transaction etc. by custom code delivery channels (for eg. SMS, e-mail etc.).
Examples of use:
- two factor authorization,
- authorize user data change,
- confirm transactions,
- confirm deleting account,
- confirm phone number,
- any other actions that requires user authorization by separate channels like e-mail, sms, voice call, etc.
Table of contents
- Installation
- How it works
- How to use
- Customization
- Delete expired codes
- Contributing
- Feedback
- License
Installation
Add package by composer
composer require tzm/authorizator
To learn how to configure the package go to How to use section
How it works
Flow of package is presented on image below:
- If action provided by user, needs additional authorization occurs, the form is displayed. User must be logged in (Of course you can implement your own logic).
- User chooses the channel (each Action can have own Channels, by default you can use one or as many channels as you want.
- Code is generated and send via given channel to a user.
- A user enters the code.
- After a successful validation of the code the custom action is executed.
How it works in details
To understand package workflow let's get deeper into details.
There are two types of classes that need to provide Tzm\Authorizator\Service\AuthorizatorAction
and Tzm\Authorizator\Service\AuthorizatorChannels\Channel
. First one is responsible for handling the given action of authorization. In this class you will set the action that will be executed after successful verification of the authorization code. This class also has the information about the return path after validation, code time expiration and allowed channels. The second one provides code delivery channel like e-mail, SMS, etc. It contains a method that delivers the authorization code to the user.
Both can be created by artisan command:
php artisan authorizator:make-action
php artisan authorizator:make-channel
Out of the box this package comes with vue component. This component has all forms and methods. There are two endpoints: authorization/send
and authorization/check
(both use POST
method). These endpoints are in Tzm\Authorizator\Controller\AuthorizationController
. There is also authorization/create
endpoint but this we will discussed later.
In the Controller in which authorization is requested (or any other place like middleware etc.) new authorization in database is created. This happens by executing static method Transaction::createAuth()
.
The Transaction
object extends Tzm\Authorizator\Service\AuthorizatorAction
class. Also new variable is stored in user session (with default name _authorizator_uuid
and contains uuid
form database). Next by response()
method the view is returned to user. So, simply the Controller will looks like:
use App\Services\AuthorizationActions\Transaction; class TransactionController extends Controller { public function create() { return Transaction::createAuth()->response(); } }
Notice: Transaction
class inherit Tzm\Authorizator\Service\AuthorizatorAction
.
You can also specify response type (Blade view or Http response code). Basically you can set property $shouldReturnView
to false to recieve the responde code 201
or you can use setResponseAsView(bool $shouldReturnView)
method.
In the vue component user chooses delivery channel (if there is more than one). Request is sent to authorization/send
endpoint by POST
method.
Next, code is delivered to the user, by a method sendMessage()
from inherited class of Tzm\Authorizator\Service\AuthorizatorChannel\Channel
. This is done by authorization/send
endpoint.
User enters this code into form. If code is valid (authorization/check
endpoint), it is set in database as used (column verified_at
is set to current time). Finally, the afterAuthorization()
from inherited Tzm\Authorizator\Service\AuthorizatorAction
class is executed. This is the most important action in this package. In this method you write the code that will be run after successful validation of the code.
Create authorization by POST method
If your application needs to create a new authorization code by POST
method you can use authorization/create
endpoint.
In your POST
request you have to add a class
parameter with name of class extending AuthorizatorAction
.
How to use
Preparations
NOTICE!
Out of the box this package uses vue component as default but if you don't wont use vue.js as your frontend framework you can create your own form handler.
To use vue component that handles authorization, declare in app.js
package's .vue
file:
Vue.component('authorizator-form', require('../../vendor/tzm/authorizator/src/resources/js/components/AuthorizatorForm').default);
Don't forget to run npm run watch
to generate assets!
Notice that your application needs to use vue.js: https://laravel.com/docs/master/frontend#writing-vue-components.
Read more about customization package in Customization section.
Create code delivery channel
You can add an example channel class by Artisan command:
php artisan authorizator:make-channel
This class will appear in app\Authorizator\Channels
folder.
Note that channel class must extend Tzm\Authorizator\Service\AuthorizatorChannels\Channel
abstract class otherwise AuthorizatorException
will be thrown.
This class requires three methods:
getChannelDescription()
- will generate description of current channel, f.ex. it could be generated from localization.json
file. It will be shown in channel choose form in the radio label.getChannelName()
- returns channel name. It will be displayed if there will be only one channel.sendMessage(User $user, $code)
- this method provide code delivery to the user. In this method you will handle how the code will be delivered to user. F.ex. if you want to send code by email you can use Laravel mail facade:Mail::to($user)->send(new SendAuthorizationCode($code))
.
Create an authorization action
Create a new Action by Artisan command:
php artisan authorizator:make-action
This class will appear in app\Authorizator\Actions
folder.
Class must declare method afterAuthorization()
. This method will be called after successful authorization f.ex. a money transfer will be executed. By getAuthorizationModel()
you can access to your Authorization
model. Finally, you have to define $allowedChannels
array contains name of code delivery channel classes that will be assign to this action f.ex.:
protected $allowedChannels = [ EmailChannel::class, SmsChannel::class, ];
Furthermore you can set the code expiration time of in $expiresInMinutes
property (it will be store in database) and in $returnRoute
returning route (executed after successful authorization). If you want to generate custom code - override generateCode()
method.
Notice that if your app implements User
model is in other namespace than App\User
you can override method
AuthorizatorAction::getUser()
.
Create view template
The package's view contains only form with vue component:
<div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Authorization</div> <div class="card-body"> <authorizator-form allowed_channels="{{ json_encode($allowedChannels) }}" > You have to verify this action. </authorizator-form> </div> </div> </div> </div> </div>
So to implement it in your application you have to publish it:
php artisan vendor:publish --tag=authorizator.views
Finally, you can extends this view for your master template. Don't worry, this view is initialized in AuthorizatorProvider
with name so there is no more action needed.
Make it works
Finally, we have all required elements: delivery channel class, action class, Blade view and generated vue component. Now it's time to set it all.
Create an example controller:
use App\Services\AuthorizationActions\Transaction; class TransactionController extends Controller { public function create() { return Transaction::createAuth()->response(); } }
Let's analyze the code.
Transaction
extends Tzm\Authorizator\Service\AuthorizatorAction
class.
In the public controller's methodcreate()
the Transaction::createAuth()
method is executed. This will insert data to database and set uuid
in session. Next method, returns default Blade view by returnView()
. That's all!
Now user can see the form and choose the authorization code deliver channel. After validation the method afterAuthorization()
form Transaction
class is executed.
Working example is available here: https://github.com/zmudzinski/authorizator-example
Send code immediately
If you would like to create an authorization and send code immediately (e.g. controller) you can use sendCode()
method from AuthorizatorAction
class.
E.g.:
VerifyPhoneAction::createAuth()->sendCode(SmsChannel::class)
This will create authorization and deliver the code by given channel (in ths case SmsChannel
)
Customization
All elements of this package are customizable.
Migrations
You can override migration by
php artisan vendor:publish --tag=authorizator.migrations
Routing
By default package routes are protected by auth
and web
middleware. They are defined in package routes.php
file. You can override them by php artisan vendor:publish --tag=authorizator.routes
. Then you have to register new route file in RouteServiceProvider
class. Add following method in RouteServiceProvider
:
protected function mapAuthorizatorRoutes(){ Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/authorizator.php')); }
Then call it in map()
method by $this->mapAuthorizatorRoutes();
:
public function map() { //... $this->mapAuthorizatorRoutes(); }
Next in config/app.php
you have to change order in providers
array. \Tzm\Authorizator\AuthorizatorProvider::class
must be before App\Providers\RouteServiceProvider::class
.
Finally you have to pass a prop to vue component with new endpoints:
<authorizator-form :allowed-channels='{!! json_encode($allowedChannels) !!}' send-endpoint="/new/path/to/send/code" verify-endpoint="/new/path/to/verify/code" > You have to verify this action. </authorizator-form>
Blade view
Default Blade view is in resource\views
folder. You have to publish this view to extend it to your master view:
php artisan vendor:publish --tag=authorizator.views
Blade view is using default Bootstrap framework.
Return HTTP code instead of Blade View
Sometimes you need to return only HTTP response code instead of blade view (e.g. if you are use endpoints to generate authorization). To do so, add property $shouldReturnView
to you Action and set to false
. This will return HTTP response with code 201
instead of blade view.
vue component
Vue component is used in Blade view. It is responsible for handling whole authorization. You can use your own vue component. Use:
php artisan vendor:publish --tag=authorizator.vue
Next you have to update declaration in app.js
declaration of component.
NOTICE! There is no needs to use vue framework. If you want you can handle forms as you want.
Localization
All of strings from PHP are translatable. All you have to do is to create a language file in resource/lang
folder f.ex. pl.json
with content:
{ "Code invalid": "Podany kod jest nieprawidłowy" }
If you want to translate strings from AuthorizationForm.vue
you can pass a translated props to component.
Delete expired codes
To remove all expired codes from database, simply use artisan command:
php artisan authorizator:purge
Contributing
- Fork it
- Create your feature branch: git checkout -b my-new-feature
- Commit your changes: git commit -am 'My new feature'
- Push to the branch: git push origin my-new-feature
- Submit a pull request
Feedback
If you have any questions or problems fell free to contact us.
License
MIT