|
| 1 | +``` |
| 2 | +██████╗ ██╗ ██╗██████╗ ███╗ ███╗ ██████╗ ███╗ ██╗███████╗████████╗███████╗██████╗ ███████╗ |
| 3 | +██╔══██╗██║ ██║██╔══██╗ ████╗ ████║██╔═══██╗████╗ ██║██╔════╝╚══██╔══╝██╔════╝██╔══██╗██╔════╝ |
| 4 | +██████╔╝███████║██████╔╝ ██╔████╔██║██║ ██║██╔██╗ ██║███████╗ ██║ █████╗ ██████╔╝███████╗ |
| 5 | +██╔═══╝ ██╔══██║██╔═══╝ ██║╚██╔╝██║██║ ██║██║╚██╗██║╚════██║ ██║ ██╔══╝ ██╔══██╗╚════██║ |
| 6 | +██║ ██║ ██║██║ ██║ ╚═╝ ██║╚██████╔╝██║ ╚████║███████║ ██║ ███████╗██║ ██║███████║ |
| 7 | +╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝ |
| 8 | +https://github.com/php-monsters/ |
| 9 | +``` |
| 10 | + |
| 11 | +# Laravel OTP |
| 12 | + |
| 13 | +## Introduction |
| 14 | + |
| 15 | +A package for Laravel One Time Password (OTP) generator and validation without Eloquent Model, since it done by *Cache*. |
| 16 | +The cache connection same as your laravel cache config and it supported: "apc", "array", "database", "file", "memcached", "redis" |
| 17 | + |
| 18 | +## Installation |
| 19 | + |
| 20 | +### Install via composer |
| 21 | + |
| 22 | +```bash |
| 23 | +composer require php-monsters/laravel-otp |
| 24 | +``` |
| 25 | + |
| 26 | +## Configuration |
| 27 | + |
| 28 | +Publish config and language file |
| 29 | + |
| 30 | +```bash |
| 31 | +php artisan vendor:publish --provider="PhpMonsters\Otp\OtpServiceProvider" |
| 32 | +``` |
| 33 | + |
| 34 | +This package publishes an `otp.php` file inside your applications's config folder which contains the settings for this package. |
| 35 | +Most of the variables are bound to environment variables, you may add Key-Value pair to the `.env` file in the Laravel application. |
| 36 | + |
| 37 | +``` |
| 38 | +OTP_FORMAT=numeric |
| 39 | +OTP_LENGTH=6 |
| 40 | +OTP_SENSITIVE=false |
| 41 | +OTP_EXPIRES_TIME=15 |
| 42 | +OTP_ATTEMPT_TIMES=5 |
| 43 | +OTP_REPEATED=true |
| 44 | +OTP_DEMO=false |
| 45 | +``` |
| 46 | + |
| 47 | +## Usage |
| 48 | + |
| 49 | +### Generate OTP |
| 50 | + |
| 51 | +```php |
| 52 | +Otp::generate(string $identifier) |
| 53 | +``` |
| 54 | + |
| 55 | +* `$identifier`: The identity that will be tied to the OTP. |
| 56 | + |
| 57 | +#### Sample |
| 58 | + |
| 59 | +```php |
| 60 | +use OTP; |
| 61 | + |
| 62 | +// in your code |
| 63 | + |
| 64 | +$password = Otp::generate('samuraee@github.com'); |
| 65 | +``` |
| 66 | + |
| 67 | +This will generate a OTP that will be valid for 15 minutes. |
| 68 | + |
| 69 | +### Validate OTP |
| 70 | + |
| 71 | +```php |
| 72 | +Otp::validate(string $identifier, string $password) |
| 73 | +``` |
| 74 | + |
| 75 | +* `$identifier`: The identity that is tied to the OTP. |
| 76 | +* `$password`: The password tied to the identity. |
| 77 | + |
| 78 | +#### Sample |
| 79 | + |
| 80 | +```php |
| 81 | +use OTP; |
| 82 | + |
| 83 | +// in your code |
| 84 | + |
| 85 | +$result = Otp::validate('samuraee@github.com', '123456'); |
| 86 | +``` |
| 87 | + |
| 88 | +#### Responses |
| 89 | + |
| 90 | +**On Success** |
| 91 | + |
| 92 | +```object |
| 93 | +{ |
| 94 | + "status": true |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +**Invalid OTP** |
| 99 | + |
| 100 | +```object |
| 101 | +{ |
| 102 | + "status": false, |
| 103 | + "error": "invalid" |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +**Expired** |
| 108 | + |
| 109 | +```object |
| 110 | +{ |
| 111 | + "status": false, |
| 112 | + "error": "expired" |
| 113 | +} |
| 114 | +``` |
| 115 | + |
| 116 | +**Max attempt** |
| 117 | + |
| 118 | +```object |
| 119 | +{ |
| 120 | + "status": false, |
| 121 | + "error": "max_attempt" |
| 122 | +} |
| 123 | +``` |
| 124 | + |
| 125 | +* Reached the maximum allowed attempts, default 10 times with each identifier |
| 126 | + |
| 127 | +### Validate OTP by Laravel Validation |
| 128 | + |
| 129 | +```php |
| 130 | +// in a `FormRequest` |
| 131 | + |
| 132 | +use PhpMonsters\Otp\Rules\OtpValidate; |
| 133 | + |
| 134 | +public function rules() |
| 135 | +{ |
| 136 | + return [ |
| 137 | + 'code' => ['required', new OtpValidate('samuraee@github.com')] |
| 138 | + ]; |
| 139 | +} |
| 140 | + |
| 141 | +// in a controller |
| 142 | + |
| 143 | +$request->validate([ |
| 144 | + 'code' => ['required', new OtpValidate('samuraee@github.com')] |
| 145 | +]); |
| 146 | +``` |
| 147 | + |
| 148 | +### Validate OTP by session id |
| 149 | + |
| 150 | +```php |
| 151 | +// Otp class |
| 152 | + |
| 153 | +$result = Otp::validate('123456'); |
| 154 | + |
| 155 | +// in a `FormRequest` |
| 156 | + |
| 157 | +use PhpMonsters\Otp\Rules\OtpValidate; |
| 158 | + |
| 159 | +public function rules() |
| 160 | +{ |
| 161 | + return [ |
| 162 | + 'code' => ['required', new OtpValidate()] |
| 163 | + ]; |
| 164 | +} |
| 165 | + |
| 166 | +// in a controller |
| 167 | + |
| 168 | +$request->validate([ |
| 169 | + 'code' => ['required', new OtpValidate()] |
| 170 | +]); |
| 171 | +``` |
| 172 | + |
| 173 | +* The setting without identifier will automatically use the session ID as the default, and the OTP generation and verification will be completed in same session (browser's cookies). |
| 174 | + |
| 175 | +## Advanced Usage |
| 176 | + |
| 177 | +### Generate OTP with options |
| 178 | + |
| 179 | +```php |
| 180 | +$password = Otp::setLength(8)->setFormat('string')->setExpires(60)->setRepeated(false)->generate('identifier-key-here'); |
| 181 | + |
| 182 | +// or array option |
| 183 | + |
| 184 | +$password = Otp::generate('identifier-key-here', [ |
| 185 | + 'length' => 8, |
| 186 | + 'format' => 'string', |
| 187 | + 'expires' => 60, |
| 188 | + 'repeated' => false |
| 189 | +]); |
| 190 | +``` |
| 191 | + |
| 192 | +* `setLength($length)`: The length of the password. Default: 6 |
| 193 | +* `setFormat($format)`: The format option allows you to decide which generator implementation to be used when generating new passwords. Options: 'string','numeric','numeric-no-zero','customize'. Default: "numeric" |
| 194 | +* `setExpires($minutes)`: The expiry time of the password in minutes. Default: 15 |
| 195 | +* `setRepeated($boolean)`: The repeated of the password. The previous password is valid when new password generated until either one password used or itself expired. Default: true |
| 196 | + |
| 197 | +### Generate OTP with customize password |
| 198 | + |
| 199 | +```php |
| 200 | +$password = Otp::setCustomize('12345678ABC@#$')->generate('identifier-key-here'); |
| 201 | +``` |
| 202 | + |
| 203 | +* `setCustomize($string)`: Random letter from the customize string |
| 204 | + |
| 205 | +### Validate OTP with specific attempt times |
| 206 | + |
| 207 | +```php |
| 208 | +$password = Otp::setAttempts(3)->validate('identifier-key-here', 'password-here'); |
| 209 | +``` |
| 210 | + |
| 211 | +* `setAttempts($times)`: The number of incorrect password attempts. Default: 5 |
| 212 | + |
| 213 | +### Validate OTP with case sensitive |
| 214 | + |
| 215 | +```php |
| 216 | +$password = Otp::setSensitive(true)->generate('identifier-key-here'); |
| 217 | + |
| 218 | +// validate |
| 219 | + |
| 220 | +$result = Otp::setSensitive(true)->validate('identifier-key-here', 'password-here'); |
| 221 | + |
| 222 | +// in controller |
| 223 | + |
| 224 | +use PhpMonsters\Otp\Rules\OtpValidate; |
| 225 | + |
| 226 | +$request->validate([ |
| 227 | + 'code' => ['required', new OtpValidate('identifier-key-here', ['sensitive' => true])] |
| 228 | +]); |
| 229 | +``` |
| 230 | + |
| 231 | +* `setSensitive($boolean)`: Requiring correct input of uppercase and lowercase letters. Default: true |
| 232 | + |
| 233 | +### Generate OTP with seperate password |
| 234 | + |
| 235 | +```php |
| 236 | +$password = Otp::setLength([4,3,4])->setSeparator(':')->generate('identifier-key-here'); |
| 237 | +``` |
| 238 | +**Sample password** |
| 239 | + |
| 240 | +``` |
| 241 | +3526:126:3697 |
| 242 | +``` |
| 243 | + |
| 244 | +* `setLength($array)`: The length of the password, use array to separate each length. |
| 245 | +* `setSeparator($string)`: The separator of the password. Default: "-" |
| 246 | + |
| 247 | +### Validate OTP with extra data |
| 248 | + |
| 249 | +```php |
| 250 | +$password = Otp::setData(['user_id' => auth()->id()])->generate('login-confirmation'); |
| 251 | +``` |
| 252 | + |
| 253 | +* `setData($var)`: Allows you to get the extra data of OTP. |
| 254 | + |
| 255 | +```php |
| 256 | +// validate |
| 257 | + |
| 258 | +$result = Otp::setDisposable(false)->validate('login-confirmation', 'password-here'); |
| 259 | + |
| 260 | +// in controller |
| 261 | + |
| 262 | +use PhpMonsters\Otp\Rules\OtpValidate; |
| 263 | + |
| 264 | +$request->validate([ |
| 265 | + 'code' => ['required', new OtpValidate('login-confirmation', ['disposable' => false])] |
| 266 | +]); |
| 267 | +``` |
| 268 | + |
| 269 | +* `setDisposable($boolean)`: The disposable of the Otp identifier, the different password is not valid when same identifier password used. Default: true |
| 270 | + |
| 271 | +**On Success Response** |
| 272 | + |
| 273 | +```object |
| 274 | +{ |
| 275 | + "status": true, |
| 276 | + "data": [ |
| 277 | + "user_id": 10 |
| 278 | + ] |
| 279 | +} |
| 280 | +``` |
| 281 | + |
| 282 | +* When you set disposable to `false`, you are able support different password with different extra data for different user in the same identifier key of the OTP. |
| 283 | + |
| 284 | +### Validate OTP with skip using |
| 285 | + |
| 286 | +```php |
| 287 | +// validate |
| 288 | + |
| 289 | +$result = Otp::setSkip(true)->validate('identifier-key-here', 'password-here'); |
| 290 | + |
| 291 | +// in controller |
| 292 | + |
| 293 | +use PhpMonsters\Otp\Rules\OtpValidate; |
| 294 | + |
| 295 | +$request->validate([ |
| 296 | + 'code' => ['required', new OtpValidate('identifier-key-here', ['skip' => true])] |
| 297 | +]); |
| 298 | +``` |
| 299 | + |
| 300 | +* `setSkip($boolean)`: Skip using the password when validate, which means you can reuse the password again. Default: false |
| 301 | +* When there is an error response to the form request, it will skip using the password, but remember to `OTP::validate(...)` in controller. |
| 302 | + |
| 303 | +### Delete OTP |
| 304 | + |
| 305 | +```php |
| 306 | +Otp::forget('identifier-key-here'); |
| 307 | +``` |
| 308 | + |
| 309 | +* Delete all password with this specific identifier |
| 310 | + |
| 311 | +### Delete specific password |
| 312 | + |
| 313 | +```php |
| 314 | +Otp::forget('identifier-key-here', 'password-here'); |
| 315 | +``` |
| 316 | + |
| 317 | +### Reset attempt times |
| 318 | + |
| 319 | +```php |
| 320 | +Otp::resetAttempt('identifier-key-here'); |
| 321 | +``` |
| 322 | + |
| 323 | +### Demo password |
| 324 | + |
| 325 | +Add the following Key-Value pair to the `.env` file in the Laravel application. |
| 326 | + |
| 327 | +``` |
| 328 | +OTP_DEMO=true |
| 329 | +``` |
| 330 | + |
| 331 | +* Demo mode for development purposes, no need to use real password to validate. |
| 332 | +* Default demo password: "1234", "123456", "12345678" |
| 333 | + |
| 334 | +## Contribution |
| 335 | + |
| 336 | +All contributions are welcome! 😄 |
| 337 | + |
| 338 | +## License |
| 339 | + |
| 340 | +The MIT License (MIT). |
| 341 | + |
| 342 | +If you enjoy this, please consider supporting me: |
| 343 | + |
| 344 | +<a href="https://monzo.me/aboozarghaffari" target="_blank">Buy Me A Coffee</a> |
0 commit comments