惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Martin Fowler
Martin Fowler
I
InfoQ
腾讯CDC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
爱范儿
爱范儿
Microsoft Security Blog
Microsoft Security Blog
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
云风的 BLOG
云风的 BLOG
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
博客园 - 聂微东
Microsoft Azure Blog
Microsoft Azure Blog
D
Docker
博客园 - 三生石上(FineUI控件)
Y
Y Combinator Blog
博客园 - Franky
Engineering at Meta
Engineering at Meta
B
Blog
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research
Jina AI
Jina AI
V
Visual Studio Blog

Scott Helme

No Hacking Required: The Manchester Airports Group Data Breach The ultimate road trip combo: Starlink Mini + UniFi Travel Router Introducing dbsc.dev: Does Your Browser Support DBSC? Device Bound Session Credentials lands in Chrome on macOS Everything I Learned Shipping Device Bound Session Credentials Connection Allowlist: a network firewall, built into the browser Connection Allowlist: a network firewall, built into the browser Top 1 Million Analysis – June 2026: The State of Crypto Top 1 Million Analysis – June 2026: The State of Crypto Top 1 Million Analysis – June 2026: Ten Years of Web Security Top 1 Million Analysis – June 2026: Ten Years of Web Security A dead CDN, a wildcard, and an attack waiting to happen: the netdna-ssl.com takeover A dead CDN, a wildcard, and an attack waiting to happen: the netdna-ssl.com takeover Why No Passkeys? Naming the Top Sites That Still Don't Support Them Why No Passkeys? Naming the Top Sites That Still Don't Support Them The Instructure Canvas Breach (2026): How XSS in a Support Ticket Compromised 275 Million Students The Instructure Canvas Breach (2026): How XSS in a Support Ticket Compromised 275 Million Students Open-Sourcing dbsc-php: a Server Library for Device Bound Session Credentials in PHP Open-Sourcing dbsc-php: a Server Library for Device Bound Session Credentials in PHP DBSC Beta at Report URI DBSC Beta at Report URI Device Bound Session Credentials: Making Stolen Cookies Useless Device Bound Session Credentials: Making Stolen Cookies Useless Passkeys, Permissions Policy and Bug Hunting in 1Password's WebAuthn Wrapper Passkeys, Permissions Policy and Bug Hunting in 1Password's WebAuthn Wrapper Open-Sourcing passkeys-php: A Security-Focused WebAuthn Library for PHP XSS Is Deadly for Passkeys: The Hidden Risk of Attestation None XSS Is Deadly for Passkeys: The Hidden Risk of Attestation None Passkeys 101: An Introduction to Passkeys and How They Work Passkeys 101: An Introduction to Passkeys and How They Work
Open-Sourcing passkeys-php: A Security-Focused WebAuthn L...
Scott Helme · 2026-05-20 · via Scott Helme

We've open-sourced passkeys-php, the WebAuthn server library we use at Report URI to protect logins with passkeys, security keys, and platform authenticators like Touch ID, Face ID, and Windows Hello.

It started as a set of local security fixes for our own production passkeys implementation. Now, rather than carrying those patches privately, we’re releasing them as a small, auditable, MIT-licensed PHP library for everyone else building normal passkey login flows.

To get started: composer require report-uri/passkeys-php
Packagist: https://packagist.org/packages/report-uri/passkeys-php

Why We Built It

Our passkeys-php is a maintained fork of the excellent lbuchs/WebAuthn, forked at upstream v2.2.0. We wanted to preserve what made that library appealing: it was small, lightweight, and understandable enough that you could actually read the code guarding your logins.

The catch was that the upstream is effectively dormant. When we had Report URI's passkeys integration penetration tested, the assessment surfaced several WebAuthn conformance issues. We wrote fixes and submitted them as PRs upstream, but they haven't been merged. Rather than carry a stack of local patches indefinitely — and leave everyone else on the same library exposed — we're shipping the fixes inline and in the open.

What We Fixed

Each fix is its own commit on main so you can audit exactly what changed and why if you'd like, but the summary is below. These were not cosmetic changes; they were the kinds of edge cases that matter when a library is responsible for deciding whether an authentication ceremony is valid.

  • Tighter origin check. The previous RP-ID match treated the RP ID as a substring suffix, so example.com would match the host evil-example.com. It
    now requires an exact match or a true subdomain.
  • Cross-origin rejection. Registration and authentication now reject ceremonies where clientDataJSON.crossOrigin === true, per WebAuthn Level 3.
  • Attestation none hardening. The none attestation statement must be an empty CBOR map, per WebAuthn §8.7. Non-empty maps are now rejected.
  • Backup flag validation. Authenticator data with the Backup State bit set but Backup Eligible unset is now rejected, per spec.
  • Token Binding rejection. Ceremonies asserting Token Binding are rejected, since the library doesn't implement it.

We Deleted Attestation

The headline change is that attestation verification is gone entirely; the library now supports only the none attestation format. Our penetration test and our own internal security reviews showed that serious risk was concentrated almost entirely in attestation-statement handling — the TPM, Packed, U2F, Android Key, Android SafetyNet and Apple formats, plus the FIDO Metadata Service plumbing and root-CA trust set. That code path is also the part of WebAuthn that our typical users don't use: browsers and platform authenticators issue attestation: "none" by default, and demanding attestation actively harms passkey UX and privacy.

So we removed it — over 1,100 lines of it. Now, getCreateArgs() always requests attestation: "none" (which the spec requires the client to honour by stripping the statement, whatever authenticator the user holds), and only fmt: "none" with an empty attStmt is accepted. The library is now positioned for the common case: SaaS-style passkey auth where the relying party only needs to know the user controls a credential bound to the RP — not which authenticator produced it. If you genuinely need enterprise attestation with a managed CA set, this isn't the library for you, and we think that's the right trade: a large, dangerous, rarely-exercised attack surface deleted instead of subtly-broken verifiers shipped to people who wouldn't enable them anyway.

Getting Started

The library autoloads under PSR-4 as ReportUri\Passkeys, with the main entry point aligned with the spec name:

use ReportUri\Passkeys\WebAuthn;
$server = new WebAuthn('My App', 'example.com');

There's a working registration and login demo in _test/ to get you going, and this is currently deployed on the Report URI production site so you can always test it there too!

Passkeys are one of the best things to happen to authentication in years, but only if the server side gets the verification right. That’s the part users never see, and the part a library has to get exactly right.

passkeys-php is our attempt to keep that code small, readable, auditable, and safe for the common case. Issues and PRs welcome.


Have you enjoyed this post or found it helpful?
☕️ Consider buying me a coffee to say thanks!
🔔 Subscribe for free notifications when I publish!
🤩 Become a member and support my content!

Tags: Report URI, Passkeys, PHP