olusegun171/laravel-mfa 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

olusegun171/laravel-mfa

Composer 安装命令:

composer require olusegun171/laravel-mfa

包简介

Multi-factor authentication for Laravel — TOTP compatible with Google Authenticator, Authy, and any RFC 6238 app.

README 文档

README

Multi-factor authentication for Laravel. Works with Google Authenticator, Authy, 1Password, Bitwarden, and any other RFC 6238 compatible app.

Tests Latest Version on Packagist Total Downloads PHP Laravel License: MIT

Features

  • TOTP codes — RFC 6238 compliant, 6-digit, 30-second window
  • QR code URI generation for any authenticator app
  • AES-256-CBC encrypted secret storage
  • 8 bcrypt-hashed one-time recovery codes
  • Clock-drift tolerance (±1 time-step)
  • TwoFactor facade + HasTwoFactor Eloquent trait

Requirements

  • PHP 8.1+
  • Laravel 10, 11, 12, or 13

Installation

composer require olusegun171/laravel-mfa

The service provider and TwoFactor facade are registered automatically via package auto-discovery.

Setup

1. Publish the config

php artisan vendor:publish --tag=two-factor-config

2. Run the migration

# Resolves the table from the guard's Eloquent model automatically
php artisan two-factor:install --guard=web

# Or pass the table directly
php artisan two-factor:install --table=admins

php artisan migrate

This adds three nullable columns to your users table:

Column Description
two_factor_secret AES-256-CBC encrypted TOTP secret
two_factor_recovery_codes JSON array of bcrypt-hashed one-time backup codes
two_factor_confirmed_at Timestamp set when the user confirms their first code

3. Add the trait to your model

use Olusegun171\TwoFactor\Traits\HasTwoFactor;

class User extends Authenticatable
{
    use HasTwoFactor;
}

Usage

See the Integration section for full usage examples split by authenticated and unauthenticated context.

Status Helpers

TwoFactor::remainingRecoveryCodes($user); // number of unused backup codes

// Model methods via HasTwoFactor trait
$user->hasTwoFactorEnabled();  // true once two_factor_confirmed_at is set
$user->hasTwoFactorPending();  // true if setup started but not yet confirmed

QR Code Identifier

By default the QR code label uses getAuthIdentifier() — typically the user's primary key. To show something friendlier (like an email address) in the authenticator app, add getTwoFactorIdentifier() to your model:

class User extends Authenticatable
{
    use HasTwoFactor;

    public function getTwoFactorIdentifier(): string
    {
        return $this->email;
    }
}

The label will appear as YourApp:user@example.com inside the authenticator app.

Configuration

// config/two-factor.php
return [
    'issuer' => env('MFA_ISSUER', null), // shown in authenticator apps; defaults to app name

    'totp' => [
        'digits'    => 6,
        'period'    => 30,   // seconds per time-step
        'window'    => 1,    // ±1 period tolerance for clock drift
        'algorithm' => 'sha1',
    ],
];

Security Notes

  • Rate-limit the challenge endpoint — 5 attempts per minute is a reasonable starting point.
  • Serve over HTTPS — codes in transit must be encrypted.
  • Recovery codes are shown once — only bcrypt hashes are stored in the database.
  • All comparisons use hash_equals() for constant-time evaluation.
  • TOTP secrets are encrypted with AES-256-CBC using a 32-byte slice of your APP_KEY.
  • Never log two_factor_secret or two_factor_recovery_codes.

Integration

Authenticated context (settings or an enforced page)

The user is already logged in. They enable 2FA from their account settings or a dedicated page to enforce the 2fa, scan the QR code, and confirm with their first code.

Enable and show the QR code

$data = TwoFactor::generate($user);

// Pass $data to your view:
// $data['qr_code_url']    — <img src="{{ $data['qr_code_url'] }}">
// $data['secret']         — manual entry fallback
// $data['recovery_codes'] — show once, store somewhere safe

Confirm the first code

try {
    TwoFactor::confirm($user, $request->code);
} catch (InvalidCodeException $e) {
    return back()->withErrors(['code' => $e->getMessage()]);
}

Disable 2FA

TwoFactor::disable($user);

Regenerate recovery codes

$codes = TwoFactor::regenerateRecoveryCodes($user); // string[]

Unauthenticated context (login flow)

The user is not yet logged in. Auth::login() is not called until the 2FA code is verified — the user is fully unauthenticated between the password step and the code step.

Step 1 — Password check (LoginController)

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Olusegun171\TwoFactor\Facades\TwoFactor;

$user = User::where('email', $request->email)->first();

if (!$user || !Hash::check($request->password, $user->password)) {
    return back()->withErrors(['email' => 'Invalid credentials.']);
}

if (TwoFactor::requiresChallenge($user)) {
    return redirect()->route('two-factor.challenge');
}

// 2FA not set up — enforced: require setup before granting access
$setup = TwoFactor::setup($user);
return redirect()->route('two-factor.setup')->with('setup', $setup);

Step 2 — Challenge routes

Wrap the challenge routes with the two-factor middleware so they redirect to login if accessed directly (no pending session).

Route::middleware('two-factor')->group(function () {
    Route::get('/two-factor/challenge',  [TwoFactorChallengeController::class, 'show'])->name('two-factor.challenge');
    Route::post('/two-factor/challenge', [TwoFactorChallengeController::class, 'store']);
    Route::post('/two-factor/recovery',  [TwoFactorChallengeController::class, 'recover']);
});

Step 3 — Challenge controller

use Olusegun171\TwoFactor\Exceptions\InvalidCodeException;
use Olusegun171\TwoFactor\Facades\TwoFactor;

// Submit a TOTP code
public function store(Request $request)
{
    $user = TwoFactor::getPendingUser();

    try {
        TwoFactor::verify($user, $request->code);
    } catch (InvalidCodeException $e) {
        return back()->withErrors(['code' => $e->getMessage()]);
    }

    TwoFactor::completeChallenge();
    Auth::login($user);
    $request->session()->regenerate();

    return redirect()->intended('/dashboard');
}

// Submit a recovery code instead
public function recover(Request $request)
{
    $user = TwoFactor::getPendingUser();

    try {
        TwoFactor::verifyRecoveryCode($user, $request->recovery_code);
    } catch (InvalidCodeException $e) {
        return back()->withErrors(['recovery_code' => $e->getMessage()]);
    }

    TwoFactor::completeChallenge();
    Auth::login($user);
    $request->session()->regenerate();

    return redirect()->intended('/dashboard');
}

completeChallenge() clears the pending session state. The caller is responsible for Auth::login() and session()->regenerate().

License

MIT — see LICENSE

olusegun171/laravel-mfa 适用场景与选型建议

olusegun171/laravel-mfa 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 21 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 05 月 11 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「Authentication」 「two-factor」 「laravel」 「totp」 「2fa」 「MFA」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 olusegun171/laravel-mfa 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 olusegun171/laravel-mfa 我们能提供哪些服务?
定制开发 / 二次开发

基于 olusegun171/laravel-mfa 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 21
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 52
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-05-11