@@ -21,6 +21,15 @@ php artisan migrate
2121Packagist
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+
2433Usage
2534``` php
2635use 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
4361Configuration
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
46131Extending: Custom Channels
47132``` php
@@ -62,4 +147,11 @@ MFA::registerChannel(new WhatsAppChannel(config('mfa.whatsapp', [])));
62147
63148// then issue
64149MFA::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