Atestácia
Atestácia je spôsob, akým autentifikátor dokazuje, čím je. Predvolene je vypnutá — formát sa zaznamená, vyhlásenie sa nikdy nečíta — a zapnete ju dvoma riadkami konfigurácie:
PASSKEYS_ATTESTATION=direct # ask authenticators to attest
PASSKEYS_ATTESTATION_TRUST=basic # and refuse anything unprovenVolania ceremónií sa vôbec nemenia — sprísnenie atestácie je konfigurácia, nie kód.
Synchronizované prístupové kľúče nikdy neatestujú. iCloud Keychain, Google Password Manager a väčšina správcov hesiel odpovie aj na požiadavku direct formátom none — kľúč, ktorý sa presúva medzi zariadeniami, nemá jedno zariadenie, ktoré by zaň ručilo. Pri self alebo basic sa každý taký kľúč odmietne výnimkou AttestationRequired, čo v praxi znamená každý kľúč, ktorý dnes vytvorí nespravovaný iPhone, iPad alebo Mac. Prísne stupne sú určené pre flotily kľúčov viazaných na zariadenie (bezpečnostné kľúče, spravované zariadenia); pre bežné prihlasovanie zákazníkov ponechajte predvolené ignore.
Zmení sa to, čo uvidíte potom:
$passkey->attestation_format; // 'packed' | 'apple' | 'none' — under `ignore`, any format the authenticator named
$passkey->attestation_type; // 'basic' | 'anonca' | 'self' | 'none' — the grade of proof establishedZaznamenaný fmt je vždy platný identifikátor formátu WebAuthn — najviac 32 tlačiteľných znakov ASCII, bez úvodzoviek a spätnej lomky. Čokoľvek iné sa odmietne výnimkou InvalidClientData pri každom stupni, vrátane ignore.
Rebríček dôvery
| attestation_trust | Čo akceptuje |
|---|---|
ignore | Všetko (predvolené). Formát sa zaznamená; vyhlásenie sa nikdy nečíta. |
self | Matematika vyhlásenia musí sedieť — podpis, prepojenie reťazca a obmedzenia CA, platnosť certifikátov. Ukotvenie sa nevyžaduje, takže prejde aj self-atestácia aj neukotvený dávkový certifikát. Vyhlásenie none — teda každý synchronizovaný kľúč — sa odmietne. |
basic | Matematika musí sedieť a reťazec certifikátov musí dosiahnuť nakonfigurovanú kotvu dôvery. Self-atestácia sa odmietne. |
Ak nastavíte attestation_trust prísnejšie ako ignore pri attestation none, zlyhá to pri štarte, nie až pri prvej stratenej registrácii. Pri ignore navyše reject_unknown_fmt odmietne formát, ktorý balík nevie overiť, aj známy formát, ktorého vyhlásenie neprejde — kotvy dôvery sa ani vtedy nepoužijú.
Podporované formáty
| fmt | Kto ho posiela | Dosiahnutý typ |
|---|---|---|
none | Všetky autentifikátory, ak nežiadate direct — a synchronizované kľúče vždy (iCloud Keychain, Google Password Manager, väčšina správcov hesiel) | none |
packed | Bezpečnostné kľúče CTAP2; zariadenia Apple spravované cez MDM s konfiguráciou Passkey Attestation | basic (s x5c) alebo self (bez neho) |
apple | Staršie kľúče Touch ID / Face ID viazané na zariadenie, z čias pred synchronizáciou cez iCloud Keychain (iOS 16 / macOS 13) | anonca |
Akýkoľvek iný formát sa pri self alebo basic odmietne s menom výnimkou UnsupportedAttestationFormat. Apple atestuje anonymne: jeho vyhlásenie nenesie podpis nad ceremóniou — certifikát kľúča namiesto toho obsahuje nonce rovné SHA-256(authenticatorData ‖ clientDataHash) a certifikuje vlastný verejný kľúč. Overí sa oboje, takže vyhlásenie z inej ceremónie tu nepoužijete. Dosiahnutý stupeň je anonca — „pravý autentifikátor Apple“, nikdy nie identita zariadenia.
Kotvy dôvery
Reťazec je ukotvený, ak jeho posledný certifikát je kotvou alebo je ňou podpísaný (x5c koreň zvyčajne vynecháva). Každý certifikát, ktorý podpísal iný certifikát — každá položka x5c nad koncovým certifikátom a kotva, ak reťazec dopĺňa — musí byť certifikačnou autoritou (RFC 5280: basicConstraints CA:TRUE a keyCertSign, ak obsahuje rozšírenie keyUsage) a každé pathLenConstraint musí platiť. Ukotvením CA vašej organizácie teda dôverujete atestačným CA, ktoré vydáva — nikdy nie koncovému certifikátu, ktorý by sám podpisoval vlastné „atestačné“ certifikáty. Bezpečnostné kľúče atestujú pod koreňom svojho výrobcu, takže ho doplňte:
'attestation_anchors' => [
'paths' => ['packed' => [storage_path('webauthn/vendor-fido-ca.pem')]],
],Balík obsahuje zverejnený Apple WebAuthn Root CA a zverejnené korene Google hardware attestation (dôveryhodné, pokiaľ nenastavíte PASSKEYS_ATTESTATION_DEFAULT_ANCHORS=false), pričom každý odtlačok je pripnutý v testoch. Vyhlásenie formátu apple sa preto pri basic ukotví bez akéhokoľvek nastavenia — Apple vo svojom x5c koreň vynecháva a pribalená kotva reťazec doplní. Týka sa to však len starších kľúčov viazaných na zariadenie; synchronizované kľúče z iCloud Keychain žiadne vyhlásenie nenesú. Korene Google slúžia pre formát android-key, ktorý sa zatiaľ neoveruje a pri self či basic sa odmietne.
Spravované zariadenia Apple atestovať vedia: s deklaratívnou konfiguráciou Passkey Attestation od Apple (MDM; iOS/iPadOS 17, macOS 14) nesú kľúče vytvorené pre uvedené domény relying party vyhlásenie packed podpísané certifikátom, ktorý pridelí vaše MDM. Takýto reťazec končí pri certifikačnej autorite vašej organizácie, nie pri koreni Apple WebAuthn — doplňte ju do attestation_anchors.paths.packed.
Každé odmietnutie uvedie formát, problematickú hodnotu a konfiguračný kľúč, ktorý ho vyrieši:
The "packed" attestation chain's root ("CN=Vendor Batch 7, O=Vendor", sha256 9f3ae1c2…,
issued by "CN=Vendor FIDO Root CA, O=Vendor") is not among the configured trust anchors.
Add the issuing CA's PEM to passkeys.attestation_anchors.paths.packed.Ak pre formát nie je nakonfigurovaná žiadna kotva — napríklad bezpečnostný kľúč pri predvolenom nastavení, ktoré pre packed žiadne korene neobsahuje — odmietnutie aj tak uvedie vydávajúcu CA, ktorú treba doplniť.
Platnosť certifikátov
Atestačné certifikáty musia byť v období platnosti na oboch hraniciach, s toleranciou attestation_clock_skew sekúnd (predvolene 60, rozsah 0–3600). Odmietne to aj skutočný hardvér: autentifikátor, ktorému vypršal dávkový certifikát, sa pri self ani basic už nezaregistruje. Je to zámer — relying party by nemala potichu schváliť expirovaný reťazec — no počítajte s tým.
Allowlist AAGUID
PASSKEYS_AAGUIDS_ALLOWED=d8522d9f-575b-4866-88a9-ba99fa02f35bPrázdny zoznam (predvolené) povolí každý model autentifikátora. AAGUID je dokázaný len pri basic, kde ho viaže dávkový certifikát; pri nižších stupňoch ho autentifikátor iba deklaruje — nakonfigurovaný zoznam sa však vynúti aj vtedy, vrátane ignore.
Pri predvolenom PASSKEYS_ATTESTATION=none prehliadače nahradia AAGUID bezpečnostného kľúča nulami (uloží sa null — model sa neprezradí), takže allowlist odmietne každý bezpečnostný kľúč, kým nepožiadate o direct. Synchronizované kľúče si AAGUID svojho poskytovateľa ponechajú v oboch prípadoch.
Zachytenie chýb
Podvrhy a odmietnutia politikou sa zachytávajú oddelene, takže sa nikdy nepomýlia. Všetky tri dedia z PasskeyException:
use RoundlyConsulting\Passkeys\Exceptions\AttestationRequired;
use RoundlyConsulting\Passkeys\Exceptions\AttestationUntrusted;
use RoundlyConsulting\Passkeys\Exceptions\InvalidAttestation;
try {
$passkey = Passkeys::for($user)->register($response);
} catch (InvalidAttestation $e) {
// the maths failed — malformed statement, bad signature, algorithm or AAGUID mismatch
} catch (AttestationUntrusted $e) {
// sound statement, refused by policy — unanchored root, invalid certification path,
// expired certificate, AAGUID not allowed
} catch (AttestationRequired $e) {
// the tier demands a statement and the authenticator sent 'none'
}Testovanie politiky
Nasmerujte kotvy na jednorazový testovací reťazec a z každého úspešného scenára packed je krátky test:
file_put_contents($path, $chain->root()->pem());
config()->set('passkeys.attestation_anchors', ['defaults' => false, 'paths' => ['packed' => [$path]]]);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 kryptomienOdoslaní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.