Skip to content

Commit 70eda74

Browse files
authored
Merge pull request #16
Update readme with package features
2 parents 00d8781 + 70a8409 commit 70eda74

File tree

1 file changed

+94
-2
lines changed

1 file changed

+94
-2
lines changed

README.md

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ php artisan migrate
2121
Packagist
2222
- `https://packagist.org/packages/coding-libs/laravel-mfa`
2323

24+
Features
25+
- Email and SMS one-time code challenges with pluggable channels
26+
- Google Authenticator compatible TOTP (RFC 6238) setup and verification
27+
- Built-in QR code generation to display TOTP provisioning URI (uses bacon/bacon-qr-code)
28+
- Remember device support via secure, hashed tokens stored in `mfa_remembered_devices`
29+
- Simple API via `MFA` facade/service for issuing and verifying codes
30+
- Publishable config and migrations; encrypted storage of TOTP secret
31+
- Extendable channel system to add providers like WhatsApp, Twilio, etc.
32+
2433
Usage
2534
```php
2635
use CodingLibs\MFA\Facades\MFA;
@@ -38,10 +47,86 @@ $ok = MFA::verifyTotp(auth()->user(), '123456');
3847
// Generate QR code (base64 PNG) from existing TOTP (uses bacon/bacon-qr-code)
3948
$base64 = MFA::generateTotpQrCodeBase64(auth()->user(), issuer: 'MyApp');
4049
// <img src="$base64" />
50+
51+
// Remember device (set cookie on successful MFA)
52+
[$token, $cookie] = [null, null];
53+
$result = MFA::rememberDevice(auth()->user(), lifetimeDays: 30, deviceName: 'My Laptop');
54+
$token = $result['token'];
55+
$cookie = $result['cookie']; // Symfony Cookie instance — attach to response
56+
57+
// Later, skip MFA if remembered device cookie is valid
58+
$shouldSkip = MFA::shouldSkipVerification(auth()->user(), MFA::getRememberTokenFromRequest(request()));
4159
```
4260

4361
Configuration
44-
- See `config/mfa.php` for email/sms/totp options.
62+
- See `config/mfa.php` for all options. Key settings:
63+
- **code_length**: OTP digits for email/sms (default 6)
64+
- **code_ttl_seconds**: Challenge expiry (default 300s)
65+
- **email**:
66+
- enabled (bool)
67+
- from_address, from_name, subject
68+
- **sms**:
69+
- enabled (bool)
70+
- driver: `log` (default) or custom integration
71+
- from: optional sender id/number
72+
- **totp**:
73+
- issuer: defaults to `config('app.name')`
74+
- digits: 6 by default
75+
- period: 30s by default
76+
- window: 1 slice tolerance by default
77+
- **remember**:
78+
- enabled (bool, default true)
79+
- cookie: cookie name (default `mfa_rd`)
80+
- lifetime_days: validity window (default 30)
81+
- path, domain, secure, http_only, same_site
82+
83+
Environment variables (examples)
84+
```
85+
MFA_EMAIL_FROM_ADDRESS="no-reply@example.com"
86+
MFA_EMAIL_FROM_NAME="Example App"
87+
MFA_EMAIL_SUBJECT="Your verification code"
88+
89+
MFA_SMS_DRIVER=log
90+
MFA_SMS_FROM="ExampleApp"
91+
92+
MFA_TOTP_ISSUER="Example App"
93+
MFA_TOTP_DIGITS=6
94+
MFA_TOTP_PERIOD=30
95+
MFA_TOTP_WINDOW=1
96+
97+
MFA_REMEMBER_ENABLED=true
98+
MFA_REMEMBER_COOKIE=mfa_rd
99+
MFA_REMEMBER_LIFETIME_DAYS=30
100+
MFA_REMEMBER_PATH=/
101+
MFA_REMEMBER_DOMAIN=
102+
MFA_REMEMBER_SECURE=null
103+
MFA_REMEMBER_HTTP_ONLY=true
104+
MFA_REMEMBER_SAME_SITE=lax
105+
```
106+
107+
Database
108+
- Publishing migrations creates tables:
109+
- `mfa_methods`: tracks enabled MFA methods per user; stores encrypted TOTP `secret`
110+
- `mfa_challenges`: stores pending OTP codes for email/sms with expiry and consumed_at
111+
- `mfa_remembered_devices`: stores hashed tokens for device recognition with IP, UA, and expiry
112+
113+
API Overview (Facade `MFA`)
114+
- **issueChallenge(Authenticatable $user, string $method): ?MfaChallenge**
115+
- **verifyChallenge(Authenticatable $user, string $method, string $code): bool**
116+
- **setupTotp(Authenticatable $user, ?string $issuer = null, ?string $label = null): array** returns `['secret','otpauth_url']`
117+
- **verifyTotp(Authenticatable $user, string $code): bool**
118+
- **generateTotpQrCodeBase64(Authenticatable $user, ?string $issuer = null, ?string $label = null, int $size = 200): ?string**
119+
- **isEnabled(Authenticatable $user, string $method): bool**
120+
- **enableMethod(Authenticatable $user, string $method, array $attributes = []): MfaMethod**
121+
- **disableMethod(Authenticatable $user, string $method): bool**
122+
- Remember device helpers:
123+
- **isRememberEnabled(): bool**
124+
- **rememberDevice(Authenticatable $user, ?int $lifetimeDays = null, ?string $deviceName = null): array** returns `['token','cookie']`
125+
- **getRememberCookieName(): string**
126+
- **getRememberTokenFromRequest(Request $request): ?string**
127+
- **shouldSkipVerification(Authenticatable $user, ?string $token): bool**
128+
- **makeRememberCookie(string $token, ?int $lifetimeDays = null): Cookie**
129+
- **forgetRememberedDevice(Authenticatable $user, string $token): int**
45130

46131
Extending: Custom Channels
47132
```php
@@ -62,4 +147,11 @@ MFA::registerChannel(new WhatsAppChannel(config('mfa.whatsapp', [])));
62147

63148
// then issue
64149
MFA::issueChallenge(auth()->user(), 'whatsapp');
65-
```
150+
```
151+
152+
Notes
153+
- SMS driver defaults to `log`. Integrate your provider by implementing a custom channel
154+
or enhancing `SmsChannel` in your app via service container bindings.
155+
- TOTP `secret` is stored encrypted by default via Eloquent cast.
156+
- QR code generation requires either Imagick or GD PHP extensions. If neither is available,
157+
generation will throw a runtime exception.

0 commit comments

Comments
 (0)