NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Two-Factor for Laravel

Prechod z inej TOTP knižnice

Samotné TOTP je prenosné. Balík dodržiava štandardný profil (SHA1, 6 číslic, 30 sekúnd), ktorý používajú autentifikačné aplikácie, takže base32 tajný kľúč vytvorený akoukoľvek knižnicou podľa RFC 6238 generuje ďalej tie isté kódy: používatelia si ponechajú záznamy v aplikácii a 2FA nemusia aktivovať znova. Kompatibilitu dokazujú statické paritné fixtures v repozitári; žiadna externá TOTP knižnica nie je závislosťou balíka.

Samo sa však neprenesie to, ako pôvodná knižnica stĺpce ukladala. Tento balík číta tajný kľúč cez cast encrypted Laravelu (Crypt::encryptString()) a záložné kódy ako JSON zoznam — v režime encrypted šifrovaný rovnako, v režime hashed ako jednosmerné haše. Každý existujúci riadok musí mať tento formát, preto si naplánujte jednorazovú migráciu dát.

Z Laravel Fortify

Fortify používa rovnaké názvy stĺpcov, no ukladá encrypt($secret) a encrypt(json_encode($codes)) — serializované hodnoty. Ak sa prečítajú bez úpravy, tajný kľúč sa vráti ako serializovaný reťazec (každé attempt() potom vyhodí InvalidBase32Exception) a záložné kódy ako prázdny zoznam. Migráciu tohto balíka nepublikujte — stĺpce už existujú. Namiesto toho vymeňte trait TwoFactorAuthenticatable z Fortify za HasTwoFactorAuthentication (pozrite Nastavenie modelu) a raz spustite túto migráciu, s rovnakým APP_KEY:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        // Fortify only adds two_factor_confirmed_at when its `confirm` option is on.
        $confirms = Schema::hasColumn('users', 'two_factor_confirmed_at');

        Schema::table('users', function (Blueprint $table) use ($confirms): void {
            if (! $confirms) {
                $table->timestamp('two_factor_confirmed_at')->nullable();
            }

            $table->unsignedBigInteger('two_factor_last_used_timestep')->nullable();
        });

        DB::table('users')->whereNotNull('two_factor_secret')->lazyById()->each(
            function (object $user) use ($confirms): void {
                DB::table('users')->where('id', $user->id)->update([
                    // Crypt::decrypt() unserializes Fortify's payload; encryptString() is what the cast reads.
                    'two_factor_secret' => Crypt::encryptString(Crypt::decrypt($user->two_factor_secret)),
                    'two_factor_recovery_codes' => $user->two_factor_recovery_codes === null
                        ? null
                        : Crypt::encryptString(Crypt::decrypt($user->two_factor_recovery_codes)),
                    // Without Fortify's confirmation step, every stored secret was a live second factor.
                    'two_factor_confirmed_at' => $confirms ? $user->two_factor_confirmed_at : now(),
                ]);
            },
        );
    }
};

Potom zabezpečte, aby sa importované kódy dali porovnať — prichádzajú v čitateľnej podobe, ukladajte ich preto vratne:

// config/two-factor.php
'recovery_codes' => [
    'count' => 8,
    'storage' => 'encrypted',
],

Pri zapnutom potvrdzovaní bol riadok z Fortify s tajným kľúčom, ale bez two_factor_confirmed_at, nedokončenou aktiváciou a aj tu zostane čakajúci. Ak ste voľbu confirm vo Fortify po migrácii vypli, nastavte two_factor_confirmed_at pre tieto riadky sami. Ak neskôr prejdete na predvolený režim hashed, zmeňte nastavenie a nechajte používateľov kódy obnoviť — zmena režimu zneplatní uložené kódy.

Z iných knižníc

Pre každý stĺpec platí rovnaké pravidlo: tajný kľúč musí byť Crypt::encryptString($base32Secret) — hodnotu v čitateľnej podobe zabaľte priamo, hodnotu serializovanú cez encrypt() najprv rozbaľte cez Crypt::decrypt(). Záložné kódy v čitateľnej podobe sa v režime encrypted zmenia na Crypt::encryptString(json_encode($codes)):

use Illuminate\Support\Facades\Crypt;

// The secret column — what the encrypted cast reads:
Crypt::encryptString($base32Secret);                    // from a plaintext secret
Crypt::encryptString(Crypt::decrypt($storedSecret));    // from an encrypt()-serialized one

// Plaintext recovery codes, under 'storage' => 'encrypted':
Crypt::encryptString(json_encode($codes));

Ak pôvodná schéma nemá stĺpec two_factor_last_used_timestep — a two_factor_confirmed_at, nastavený pre každého aktivovaného používateľa — pridajte ich. Stĺpec pre ochranu proti opakovaniu má rovnaký typ, aký vytvára makro:

Schema::table('users', function (Blueprint $table): void {
    $table->unsignedBigInteger('two_factor_last_used_timestep')->nullable();
});

Iné názvy stĺpcov

Ak sa vaše existujúce stĺpce volajú inak, namiesto premenovania ich premapujte — všetky tabuľky účtov zdieľajú jednu mapu:

// config/two-factor.php — remap for non-standard schemas
'columns' => [
    'secret' => 'two_factor_secret',
    'recovery_codes' => 'two_factor_recovery_codes',
    'confirmed_at' => 'two_factor_confirmed_at',
    'last_used_timestep' => 'two_factor_last_used_timestep',
],

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.