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

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Azure Blog
Microsoft Azure Blog
Cloudbric
Cloudbric
I
InfoQ
V
V2EX
博客园_首页
The Register - Security
The Register - Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
S
Secure Thoughts
Vercel News
Vercel News
Forbes - Security
Forbes - Security
云风的 BLOG
云风的 BLOG
PCI Perspectives
PCI Perspectives
L
LINUX DO - 最新话题
D
DataBreaches.Net
H
Hacker News: Front Page
Application and Cybersecurity Blog
Application and Cybersecurity Blog
B
Blog RSS Feed
A
About on SuperTechFans
N
News and Events Feed by Topic
Apple Machine Learning Research
Apple Machine Learning Research
Help Net Security
Help Net Security
Attack and Defense Labs
Attack and Defense Labs
N
Netflix TechBlog - Medium
Spread Privacy
Spread Privacy
F
Full Disclosure
Recorded Future
Recorded Future
AWS News Blog
AWS News Blog
博客园 - 【当耐特】
The Cloudflare Blog
T
Threatpost
T
Tor Project blog
Google DeepMind News
Google DeepMind News
C
CXSECURITY Database RSS Feed - CXSecurity.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
M
MIT News - Artificial intelligence
A
Arctic Wolf
C
Check Point Blog
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News - Newest:
Hacker News - Newest: "LLM"
WordPress大学
WordPress大学
Cyberwarzone
Cyberwarzone
小众软件
小众软件
C
Cyber Attacks, Cyber Crime and Cyber Security
P
Proofpoint News Feed
Security Latest
Security Latest
The Last Watchdog
The Last Watchdog

Scott Helme

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: Ten Years of Web Security 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 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 DBSC Beta at Report URI Device Bound Session Credentials: Making Stolen Cookies Useless Passkeys, Permissions Policy and Bug Hunting in 1Password's WebAuthn Wrapper XSS Is Deadly for Passkeys: The Hidden Risk of Attestation None Passkeys 101: An Introduction to Passkeys and How They Work Anatomy of a WooCommerce Skimmer: A Technical Deep-Dive Under Attack: Responding to the Rise of Info-Stealer Threats Security considerations when using Passkeys on your website Fighting an active Magecart Campaign Amazing Refresh — A Malicious Chrome Extension Running Malware in the Browser Bringing in the experts; Having our Passkeys implementation Security Tested Launching Passkeys support on Report URI! 🗝️ When “One in a Billion” Happens Every Day: Scaling Redis at Report URI Leverage our treasure trove of Threat Intelligence data XSS Ranked #1 Top Threat of 2025 by MITRE and CISA DNS-PERSIST-01; Handling Domain Control Validation in a short-lived certificate World
Open-Sourcing passkeys-php: A Security-Focused WebAuthn Library for PHP
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