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

Service provider viaže každý kontrakt na predvolený singleton. Naviažte vlastnú implementáciu a vymení sa všade:

KontraktPredvolená väzbaÚčel
PasskeyServicePasskeyManagerKoreň fasády — for($user), ceremónia bez mena a attestationFormats().
ChallengeRepositoryCacheChallengeRepositoryJednorazové úložisko challenge s TTL.
AttestationVerifierAttestationGatePolitika dôvery atestácie — rebríček, kotvy, allowlist AAGUID.
HasPasskeysVáš model cez InteractsWithPasskeysModel, ktorý vlastní prístupové kľúče.

Namiesto výmeny celej služby radšej previažte jednu akciu (napríklad RevokePasskeyAction) — manažér aj handle účtu získavajú každú akciu z kontajnera, takže zmena platí pre fasádu, injektovanú službu aj metódy modelu. Úplne vlastný PasskeyService implementuje štyri metódy — for($user), ktorá vracia handle UserPasskeys, authenticationOptions(?$overrides), authenticate($response, ?$expect) a attestationFormats().

Vlastné úložisko challenge

CacheChallengeRepository ukladá každú challenge pod passkeys:challenge:<ceremonyId> v cache store-e podľa challenge.store a pull() ju načíta a zmaže pod zámkom store-u, takže z dvoch súbežných požiadaviek na jednu ceremóniu ju dostane práve jedna. Ak chcete challenge ukladať inde, implementujte kontrakt a naviažte ho:

use RoundlyConsulting\Passkeys\Contracts\ChallengeRepository;
use RoundlyConsulting\Passkeys\DataTransferObjects\ChallengeData;

final class DatabaseChallengeRepository implements ChallengeRepository
{
    public function put(string $ceremonyId, ChallengeData $challenge, int $ttl): void { /* … */ }
    public function pull(string $ceremonyId): ?ChallengeData { /* fetch + delete atomically */ }
}

// In a service provider:
$this->app->singleton(ChallengeRepository::class, DatabaseChallengeRepository::class);

pull() musí vrátiť null, ak challenge chýba, vypršala alebo už bola spotrebovaná, a musí zostať jednorazová aj pri súbežnosti — samotné načítanie a následné samostatné zmazanie nestačí.

Pridanie formátu atestácie

Atestácia je rozdelená na dve časti. Overovače formátov dokazujú len matematiku a vracajú AttestationResult; o dôvere rozhoduje výhradne AttestationGate — rebríček, prepojenie reťazca, platnosť, kotvy aj allowlist AAGUID. Napíšte overovač:

use RoundlyConsulting\Crypto\Cose\AuthenticatorData;
use RoundlyConsulting\Passkeys\Attestation\AttestationResult;
use RoundlyConsulting\Passkeys\Attestation\AttestationVerifier;
use RoundlyConsulting\Passkeys\DataTransferObjects\AttestationObject;
use RoundlyConsulting\Passkeys\Enums\AttestationType;

final class AndroidSafetynetVerifier implements AttestationVerifier
{
    public function verify(
        AttestationObject $attestation,
        AuthenticatorData $authenticatorData,
        string $clientDataHash,
    ): AttestationResult {
        // Prove the maths; throw InvalidAttestation on any failure. Never rule on
        // trust — the gate owns that.
        return AttestationResult::chained('android-safetynet', AttestationType::Basic, $chain);
    }
}

Potom znovu naviažte register s pridaným overovačom — všetky rozhodnutia o dôvere zostávajú v gate:

use Illuminate\Contracts\Foundation\Application;
use RoundlyConsulting\Passkeys\Attestation\AppleAttestationVerifier;
use RoundlyConsulting\Passkeys\Attestation\AttestationVerifierRegistry;
use RoundlyConsulting\Passkeys\Attestation\NoneAttestationVerifier;
use RoundlyConsulting\Passkeys\Attestation\PackedAttestationVerifier;
use RoundlyConsulting\Passkeys\Support\CredentialCrypto;

// In a service provider:
$this->app->singleton(AttestationVerifierRegistry::class, fn (Application $app) => new AttestationVerifierRegistry([
    'none' => new NoneAttestationVerifier,
    'packed' => new PackedAttestationVerifier($app->make(CredentialCrypto::class)),
    'apple' => new AppleAttestationVerifier,
    'android-safetynet' => new AndroidSafetynetVerifier,
]));

Reťazce certifikátov skladajte zo surových DER bajtov, ktoré nesie CBOR, nikdy nie z base64 pomocníka pre x5c — ten zodpovedá tvaru JOSE a odmietol by každý skutočný autentifikátor. Ak chcete celú politiku atestácie nahradiť, naviažte vlastný AttestationVerifier; ceremónia volá len ten.

Vlastné napojenie používateľa

Ak potrebujete špecifické ukladanie identifikátora alebo odvodenie mena, implementujte HasPasskeys priamo namiesto traitu. Ceremónie potrebujú len štyri metódy kontraktu — dbajte len na to, aby passkeyUserHandle() zostal stabilný.

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.