Passkeys are winning the browser login race.
And they should.
WebAuthn and FIDO2 solved a huge part of the authentication problem: phishing-resistant, browser-native, public-key authentication.
But the more I worked on real systems, the more I noticed a gap.
Not every authentication problem happens inside a browser.
Some happen on a point-of-sale terminal.
Some happen offline.
Some happen inside a legacy OTP form that cannot be rewritten overnight.
Some happen during a high-value transaction where the user must visually confirm an amount.
Some happen under coercion.
And some require approval from more than one device.
That is the gap that led me to PulseProof Sentinel Protocol, or PPS.
PPS is an experimental open authentication protocol that replaces shared-secret TOTP-style codes with signed, time-bound, asymmetric proofs called Pulses.
You can explore the project here:
https://pps-protocol.github.io
The Problem With TOTP
TOTP is everywhere.
It is simple, widely supported, and easy to deploy.
But it has a structural weakness:
code = HMAC(shared_secret, time)
The server knows the secret.
If the server database is breached, the attacker can generate valid codes.
That is not ideal.
Public-key authentication solves this. The server should not need to know the secret that proves identity.
That is the core idea behind PPS:
Pulse = Sign(private_key, time + rp + nonce + counter + context + policy)
The userβs device holds the private key.
The server stores only the public key.
The proof is signed, time-bound, replay-protected, and bound to the relying party.
PPS Is Not a WebAuthn Replacement
This is important.
PPS is not trying to replace WebAuthn.
If you are building browser-based passwordless login, WebAuthn is usually the right answer.
PPS is designed to complement WebAuthn.
It targets the operational gaps where WebAuthn is unavailable, impractical, or insufficient:
- offline authentication
- legacy OTP input forms
- QR-code and deep-link authentication
- constrained hardware terminals
- point-of-sale and IoT devices
- human-visible transaction confirmation
- silent duress signaling
- offline multi-device threshold approval
In other words:
WebAuthn is for passkeys.
PPS is for the authentication flows that still live outside the passkey world.
What Is a Pulse?
A Pulse is a signed authentication statement.
It can be bound to several things:
- a relying-party identifier
- a time epoch
- a server nonce
- a monotonic counter
- an expiration window
- a security policy
- a transaction hash
- environmental context
This makes PPS flexible.
A Pulse can be used for simple login.
It can also be used for transaction signing, offline terminal authentication, or multi-device approval.
The protocol uses deterministic CBOR encoding and Ed25519 signatures.
The mandatory profile is:
PPS-ED25519-CBOR30
You can read the full specification here:
https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html
The documentation is available here:
https://pps-protocol.github.io/pulseproof-sentinel/docs/
The protocol is also submitted as an IETF Internet-Draft:
https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/
The Developer Story: PHP and Laravel
A protocol is only useful if people can implement it.
That is why the first sample implementation is available in PHP.
The core package is framework-agnostic:
https://github.com/pps-protocol/pps-php
You can install it with Composer:
composer require pps-protocol/pps-php
Package website:
https://pps-protocol.github.io/pps-php/
Documentation:
https://pps-protocol.github.io/pps-php/docs/
Packagist:
https://packagist.org/packages/pps-protocol/pps-php
For Laravel applications, there is a dedicated integration package:
https://github.com/pps-protocol/laravel-pps
Install it with:
composer require pps-protocol/laravel-pps
Then run:
php artisan pps:install
The Laravel package provides:
- service provider
- publishable configuration
- API routes
- HTTP controller
- facade
- Artisan commands
- storage backend integration
- transaction challenge endpoints
- silent duress handling support
Laravel package website:
https://pps-protocol.github.io/laravel-pps/
Packagist:
https://packagist.org/packages/pps-protocol/laravel-pps
A Small Example
At the protocol level, the idea is simple.
The client signs a Pulse:
use Pps\Client\AuthenticatorClient;
$client = new AuthenticatorClient($clientState);
$pulse = $client
->rpId('example.com')
->nonce($nonceFromServer)
->createPulse();
The server verifies it using the stored public key.
No shared OTP secret is required.
In Laravel, the package exposes endpoints such as:
GET /pps/health
GET /pps/challenge
POST /pps/register
POST /pps/verify
POST /pps/transaction/challenge
POST /pps/transaction/verify
This makes it easy to integrate PPS into an existing authentication or transaction-signing flow.
Transaction Signing Is Where PPS Becomes Interesting
One of my favorite PPS features is transaction signing.
Imagine a withdrawal:
Amount: 2,500,067 IRR
Trust Code: 49371867
The last two digits of the Trust Code come from the transaction amount.
This creates a human-visible connection between the cryptographic proof and the transaction being approved.
The user can confirm:
Yes, the code I see matches the amount I requested.
This is especially useful for:
- banking
- fintech
- crypto withdrawals
- admin approvals
- high-value payments
- corporate treasury flows
PPS can bind the transaction hash, amount, session, and policy into the signed Pulse.
That is much stronger than sending a generic OTP code.
Silent Duress: Authentication Under Coercion
Another important area is duress.
What happens if someone is forced to authenticate?
Traditional OTP systems do not have a good answer.
PPS introduces an optional duress mechanism.
The user can authenticate with a hidden duress key.
The resulting Pulse is cryptographically valid, but the server recognizes it as a Honey-Pulse.
The server can return a normal-looking success response while internally:
- restricting account capabilities
- blocking high-value operations
- delaying settlement
- triggering a silent alert
- preserving audit logs
This is sensitive territory, and implementation matters a lot.
But for high-risk accounts, it is a powerful concept.
Offline and Multi-Device Flows
PPS also supports offline authentication.
Because a Pulse is signed and time-bound, it can be generated without a live network round-trip.
Offline mode requires stricter rate limiting and careful operational design, but it is useful for:
- terminals
- IoT devices
- field equipment
- unstable networks
- emergency access
PPS also supports offline multi-device threshold approval.
For example:
2-of-2: phone + watch
2-of-3: phone + laptop + hardware key
This is useful when a single device should not be enough to approve a sensitive action.
The Ecosystem
The PPS project is organized under a GitHub organization:
https://github.com/pps-protocol
The main repositories are:
PulseProof Sentinel Protocol
The specification repository.
https://github.com/pps-protocol/pulseproof-sentinel
Website:
https://pps-protocol.github.io/pulseproof-sentinel/
Specification:
https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html
Documentation:
https://pps-protocol.github.io/pulseproof-sentinel/docs/
pps-php
The core PHP implementation.
https://github.com/pps-protocol/pps-php
Website:
https://pps-protocol.github.io/pps-php/
Documentation:
https://pps-protocol.github.io/pps-php/docs/
Packagist:
https://packagist.org/packages/pps-protocol/pps-php
laravel-pps
The Laravel integration package.
https://github.com/pps-protocol/laravel-pps
Website:
https://pps-protocol.github.io/laravel-pps/
Packagist:
https://packagist.org/packages/pps-protocol/laravel-pps
Why Explore PPS?
PPS is experimental.
It has not been independently audited.
It is not ready to replace your production authentication system tomorrow.
But if you care about authentication design, it is worth exploring.
It is especially interesting if you are working on:
- fintech authentication
- crypto exchange security
- offline device login
- POS terminals
- IoT authentication
- transaction signing
- high-value approval workflows
- duress-aware accounts
- multi-device authorization
- legacy OTP migration
PPS asks a simple question:
Why should the server ever store a shared OTP secret when it can verify a signature instead?
Start Here
The best place to start is the project website:
https://pps-protocol.github.io
Then read the specification:
https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html
If you are a PHP developer, try the core package:
composer require pps-protocol/pps-php
If you are using Laravel, install the Laravel integration:
composer require pps-protocol/laravel-pps
And if you are interested in protocol design, review the IETF Internet-Draft:
https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/
PPS is early, experimental, and open for feedback.
If you believe authentication should move beyond shared secrets, give it a look.
Top comments (0)