Init
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# OTP Authentication
|
||||
|
||||
Staff authentication uses a passwordless OTP flow. No password is stored or required.
|
||||
|
||||
---
|
||||
|
||||
## Flow
|
||||
|
||||
1. Staff enters their email on the login page
|
||||
2. A 6-digit code is generated, stored on the `staff` record, and emailed
|
||||
3. Staff enters the code — if valid and not expired, they are logged in
|
||||
|
||||
---
|
||||
|
||||
## Implementation
|
||||
|
||||
### OtpService
|
||||
|
||||
`Modules\Core\Services\OtpService` handles generation and validation.
|
||||
|
||||
```php
|
||||
// Generate and email a code
|
||||
$otpService->generateAndSend(string $email): bool
|
||||
|
||||
// Validate a submitted code — returns the Staff model on success, null on failure
|
||||
$otpService->validate(string $email, string $code): ?Staff
|
||||
```
|
||||
|
||||
Codes expire after **10 minutes**. After a successful validation the code is cleared from the record.
|
||||
|
||||
### Database
|
||||
|
||||
Two columns on the `lunar_staff` table (added by `2026_05_06_000001_add_otp_to_lunar_staff_table`):
|
||||
|
||||
| Column | Type | Purpose |
|
||||
|---|---|---|
|
||||
| `otp_code` | string, nullable | The generated code |
|
||||
| `otp_expires_at` | timestamp, nullable | Expiry time |
|
||||
|
||||
### Login Page
|
||||
|
||||
`Modules\Core\Filament\Pages\Login` is a Filament `SimplePage` registered as the panel login via `AppServiceProvider`:
|
||||
|
||||
```php
|
||||
LunarPanel::panel(fn (Panel $panel) => $panel->login(Login::class));
|
||||
```
|
||||
|
||||
It has two steps rendered in `core::filament.pages.login`:
|
||||
|
||||
- **Step 1** — email form, submits to `requestOtp()`
|
||||
- **Step 2** — code form, submits to `authenticate()`
|
||||
|
||||
After a valid code `canAccessPanel()` is checked before the session is established.
|
||||
|
||||
### Email
|
||||
|
||||
`Modules\Core\Mail\OtpMail` sends the code using the `core::mail.otp` view.
|
||||
|
||||
---
|
||||
|
||||
## Disabling 2FA
|
||||
|
||||
Lunar's built-in 2FA plugin is disabled in `AppServiceProvider` since the OTP login replaces it:
|
||||
|
||||
```php
|
||||
LunarPanel::disableTwoFactorAuth();
|
||||
```
|
||||
Reference in New Issue
Block a user