https://github.com/cuongdinhngo/otp-auth
The OTP Auth package allows you to authenticate with one time password access (OTP)
https://github.com/cuongdinhngo/otp-auth
authentication laravel otp self
Last synced: 9 months ago
JSON representation
The OTP Auth package allows you to authenticate with one time password access (OTP)
- Host: GitHub
- URL: https://github.com/cuongdinhngo/otp-auth
- Owner: cuongdinhngo
- License: mit
- Created: 2021-06-10T04:05:31.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2021-09-06T14:32:01.000Z (almost 5 years ago)
- Last Synced: 2025-05-08T05:44:48.387Z (about 1 year ago)
- Topics: authentication, laravel, otp, self
- Language: PHP
- Homepage:
- Size: 32.2 KB
- Stars: 9
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Laravel OTP AUTH
This package allows you to authenticate with one time password access (OTP).
Example Usage:
```php
Route::get("/notify", function(){
return App\Models\User::find(1)->notify(new App\Authentication\SendOtp('mail', 4, 10));
});
Route::get("/auth-otp/{otp}", function(){
return App\Models\User::authByOtp(request()->otp, '84905.......');
});
Route::get("/check-otp/{otp}", function(){
return App\Models\User::find(1)->checkOtp(request()->otp);
});
```
## Contents
- [Installation](#installation)
- [Usage](#usage)
- [Generate OTP](#generate-otp)
- [Verify OTP](#verify-otp)
- [Basic identification](#basic-identification)
- [Demo](#demo)
- [Credits](#credits)
## Installation
1- Add the package to your dependencies.
```
$ composer require cuongdinhngo/otp-auth
```
2- Run the command:
```php
php artisan auth:otp {ClassName}
```
Example:
```php
php artisan auth:otp Authentication/SendOtp
```
_`SendOtp` class and `HasOtpAuth` trait are auto-generated at `app/Authentication` directory._
_`CreateNotificationsTable` class is alseo auto-generated at `app/database/migrations`._
3- Apply the migrations:
_It will create a table called `notifications` to store generated OTP information._
```
$ php artisan migrate
```
## Usage
### Generate OTP
You can generate OTP via email or SMS
```php
Route::get("/notify", function(){
return App\Models\User::find(1)->notify(new App\Authentication\SendOtp(['mail', 'nexmo']));
});
```
This package allows you to alter OTP length and lifetime
```php
Route::get("/notify", function(){
$length = 4;
$liftime = 10; //minutes
return App\Models\User::find(1)->notify(new App\Authentication\SendOtp(['mail', 'nexmo']), $length, $liftime);
});
```
**OTP default length**: The default length is `6`.
**OTP default lifetime**: The default lifetime is `1` minute.
There is the detail of auto-generate `SentOTP` class:
```php
otp = $this->generateOtp($otpLength ?? self::OPT_LENGTH);
$this->lifeTime = $lifeTime ?? self::OPT_LIFETIME;
$this->defaultChannels = $this->verifyChannels($channels);
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return $this->defaultChannels;
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('Your OTP is '.$this->otp)
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
'otp' => $this->otp,
'expired_at' => now()->addMinutes($this->lifeTime)->toDateTimeString(),
];
}
/**
* Get the Nexmo / SMS representation of the notification.
*
* @param mixed $notifiable
*
* @return mixed
*/
public function toTwilio($notifiable)
{
return (new TwilioMessage)
->to("+8439xxxxxxx")
->from("+xxxxxxxxxx")
->body('OTP AUTH is '.$this->otp);
}
/**
* Generate OTP
*
* @param integer|string $n
*
* @return string
*/
public function generateOtp($n)
{
$generator = "09xxxxxxx";
$result = "";
for ($i = 1; $i <= $n; $i++) {
$result .= substr($generator, (rand()%(strlen($generator))), 1);
}
return $result;
}
/**
* Verify channels
*
* @param string|array $channels
*
* @return array
*/
public function verifyChannels($channels)
{
if ($channels && is_array($channels)) {
return array_merge($this->defaultChannels, $channels);
}
if ($channels && is_string($channels)) {
array_push($this->defaultChannels, $channels);
}
return $this->defaultChannels;
}
}
```
**toTwilio**: This method is implemented by importing [delivery-channels](https://github.com/cuongdinhngo/delivery-channels).
### Verify OTP
After sent OTP via your configed methods, you call `authByOtp` to authenticate
```php
Route::get("/auth-otp/{otp}", function(){
return App\Models\User::authByOtp(request()->otp, '84905123456');
});
```
Based on your credentials, you might authenticate with email or phone number
#### Set up the credentials:
In this case, you can apply `User` model which must use `HasOtpAuth` trait
```php
. . . .
use App\Authentication\HasOtpAuth;
class User extends Authenticatable
{
use Notifiable;
use HasOtpAuth;
protected $credential = 'mobile';
. . . .
```
Let see more detail `HasOtpAuth` trait
```php
otp();
return $this->validateOtp($authenticator, $otp);
}
/**
* Get OTP data
*
* @return \Illuminate\Notifications\DatabaseNotification
*/
public function otp()
{
return $this->notifications()
->where('type', 'LIKE', '%SendOtp%')
->whereNull('read_at')
->first();
}
/**
* Validate OTP
*
* @param \Illuminate\Notifications\DatabaseNotification $authenticator
* @param mixed $otp
*
* @return void
*/
public function validateOtp($authenticator, $otp)
{
$result = false;
if (is_null($authenticator)) {
return response()->json($result,200);
}
if ($authenticator
&& now()->lte($authenticator->data['expired_at'])
&& $authenticator->data['otp'] == $otp
) {
$result = true;
}
$authenticator->markAsRead();
return response()->json($result,200);
}
/**
* Authenticate by OTP
*
* @param string $otp
* @param string $credentialValue
* @return void
*/
public static function authByOtp($otp, $credentialValue)
{
$model = new static;
$credentialName = property_exists($model,'credential') ? $model->credential : 'email';
$authenticator = $model->where($credentialName, '=', $credentialValue)->first();
if (is_null($authenticator)) {
return response()->json(false,200);
}
$authenticator = $authenticator->notifications()
->where('type', 'LIKE', '%SendOtp%')
->whereNull('read_at')
->first();
return $model->validateOtp($authenticator, $otp);
}
}
```
### Basic identification
In some cases, you just need to identify the right access, you might need to execute `checkOtp` method
```php
Route::get("/check-otp/{otp}", function(){
return auth()->user->checkOtp(request()->otp);
});
```
### Demo
This is demo soure code.
[Laravel Colab](https://github.com/cuongdinhngo/lara-colab/blob/master/alpha/routes/web.php)
## Credits
- Ngo Dinh Cuong
[LinkedIn](https://www.linkedin.com/in/ngodinhcuong/)