<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hossein Hezami</title>
    <description>The latest articles on DEV Community by Hossein Hezami (@hosseinhezami).</description>
    <link>https://dev.to/hosseinhezami</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F205584%2Ff7b90254-50f9-4454-990d-fc2e6f56eee1.jpeg</url>
      <title>DEV Community: Hossein Hezami</title>
      <link>https://dev.to/hosseinhezami</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hosseinhezami"/>
    <language>en</language>
    <item>
      <title>oving Beyond TOTP: Why the PulseProof Sentinel (PPS) Protocol is the Future of Offline Authentication</title>
      <dc:creator>Hossein Hezami</dc:creator>
      <pubDate>Wed, 29 Jul 2026 08:38:21 +0000</pubDate>
      <link>https://dev.to/hosseinhezami/oving-beyond-totp-why-the-pulseproof-sentinel-pps-protocol-is-the-future-of-offline-4bdl</link>
      <guid>https://dev.to/hosseinhezami/oving-beyond-totp-why-the-pulseproof-sentinel-pps-protocol-is-the-future-of-offline-4bdl</guid>
      <description>&lt;p&gt;Time-based One-Time Passwords (TOTP)—the technology behind Google Authenticator and Microsoft Authenticator—have kept us safe for over a decade. But as cyber threats evolve and systems increasingly move to isolated, semi-offline, or edge environments, the foundational vulnerabilities of TOTP are starting to show. &lt;/p&gt;

&lt;p&gt;Enter the &lt;strong&gt;PulseProof Sentinel Protocol (PPS)&lt;/strong&gt;, an innovative Internet-Draft registered with the IETF by researcher Hossein Hezami. PPS introduces an elegant shift in cryptographic paradigms: &lt;strong&gt;replacing shared-secret symmetric authentication with time-bound asymmetric proofs.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  In this article, we’ll dive deep into why PPS is a game-changer, how it operates in 100% offline environments, and how it handles physical coercion with absolute stealth.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The Fatal Flaws of Traditional TOTP
&lt;/h2&gt;

&lt;p&gt;To appreciate PulseProof Sentinel, we must first look at what makes traditional 2FA vulnerable:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Shared Secret Trap:&lt;/strong&gt; TOTP relies on a shared symmetric key stored on both your device and the server. If a hacker breaches the server’s database, they steal the raw seeds for &lt;em&gt;every single user&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lack of Forward Secrecy:&lt;/strong&gt; If someone compromises your 2FA secret key today, they can often generate future codes or intercept past sessions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. &lt;strong&gt;No Safety Valve for Physical Coercion:&lt;/strong&gt; If an attacker physically forces you to open your account under duress, traditional 2FA leaves you with zero options to signal for help safely.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What is PulseProof Sentinel (PPS)?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;PulseProof Sentinel (PPS)&lt;/strong&gt; is an experimental authentication protocol designed specifically for constraint-heavy, offline, or high-risk environments (like IoT networks, remote hardware, or air-gapped point-of-sale terminals). &lt;/p&gt;

&lt;p&gt;Instead of generating a random 6-digit number based on a shared secret, PPS generates a cryptographically signed message known as a &lt;strong&gt;"Pulse."&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Zero Server-Side Secrets (Asymmetric Architecture)PPS leverages asymmetric cryptography (&lt;strong&gt;Ed25519&lt;/strong&gt;). The server stores &lt;strong&gt;only your Public Key&lt;/strong&gt;. If the server's database is completely leaked, the attacker gains absolutely nothing that could help them spoof a pulse. Your Private Key remains strictly isolated within your device's Secure Enclave.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  2. Time-Counter Hybrid RatchetingTo prevent replay attacks and ensure robust security, PPS uses an asymmetric ratchet mechanism based on &lt;strong&gt;SHA-256&lt;/strong&gt; and &lt;strong&gt;HKDF&lt;/strong&gt;. Every time a pulse is generated, the private key evolves and the old key is discarded forever. This guarantees strict &lt;strong&gt;Forward Secrecy&lt;/strong&gt;.
&lt;/h3&gt;




&lt;h2&gt;
  
  
  How It Works in 100% Offline Environments
&lt;/h2&gt;

&lt;p&gt;One of the biggest engineering achievements of PPS is its ability to validate credentials without requiring any internet connection on the client side. &lt;/p&gt;

&lt;p&gt;Imagine an air-gapped smart door lock or an offline POS machine in a remote area:&lt;/p&gt;

&lt;p&gt;[ Offline Client Device ]&lt;br&gt;
│ (Generates Compact CBOR Pulse via Ed25519)&lt;br&gt;
▼&lt;br&gt;
[ QR Code / NFC / BLE ]&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
[ Air-Gapped Verifier Terminal ] ───► (Validates Signature via Local Public Key)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Compact Pulse:&lt;/strong&gt; The client packs the protocol version, timestamp, unique nonce, counter, and a signature into a highly compressed &lt;strong&gt;CBOR&lt;/strong&gt; (Concise Binary Object Representation) payload.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passive Data Transfer:&lt;/strong&gt; This tiny payload is translated into a dynamic QR Code, an NFC burst, or a Bluetooth Low Energy (BLE) packet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Dynamic Acceptance Window:&lt;/strong&gt; What happens if the offline device's internal clock drifts? PPS introduces a &lt;strong&gt;Sliding Validation Window&lt;/strong&gt;. When the verifier receives a pulse, it checks a range of future/past time slots. Once validated, the verifier automatically calculates the exact time drift, saves it to the user's profile, and seamlessly self-corrects for future validations—all without internet sync!&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Coolest Feature: The "Honey-Pulse" (Duress Signaling)
&lt;/h2&gt;

&lt;p&gt;In high-security deployments, physical threats are a real attack vector. PPS addresses this with a brilliant psychological and cryptographic mechanism called &lt;strong&gt;Honey-Pulse&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When configuring your device, PPS initiates twin, parallel key-rotation tracks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Normal Track:&lt;/strong&gt; For everyday, risk-free authentications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honey Track:&lt;/strong&gt; Triggered only under duress (via an alternative PIN, a specific gesture, or a hidden panic button).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If an attacker forces you to log in, you trigger the Honey Track. The device outputs a pulse that looks &lt;strong&gt;mathematically flawless&lt;/strong&gt; to any onlooker. The attacker sees a successful login animation on the device screen. &lt;/p&gt;

&lt;p&gt;However, when the pulse hits the online backend server, it instantly flags the hidden "Honey" indicator. The server subtly sandboxes the session, caps transactional limits to zero, and quietly triggers silent alarms or relays location coordinates to security personnel—all while keeping the attacker completely oblivious.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current Status and Developer Ecosystem
&lt;/h2&gt;

&lt;p&gt;Because security standards require rigorous peer reviews, PPS is currently classified as an &lt;strong&gt;Experimental Internet-Draft&lt;/strong&gt; within the IETF. It is undergoing active evaluation to ensure it stands up to side-channel attacks and edge-case vulnerabilities.&lt;/p&gt;

&lt;p&gt;However, the ecosystem is growing fast. If you are a developer looking to experiment with this cutting-edge protocol, open-source packages are already available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core PHP Implementation: &lt;code&gt;pps-php&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Laravel Framework Integration: &lt;code&gt;laravel-pps&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion: Is This the Future?
&lt;/h2&gt;

&lt;p&gt;While mass-market web apps are currently pivoting toward Passkeys (WebAuthn/FIDO2), &lt;strong&gt;PulseProof Sentinel bridges the critical gaps where FIDO2 cannot easily reach&lt;/strong&gt;—specifically in completely air-gapped, zero-connectivity environments, and scenarios requiring native, cryptographically hidden duress handling.&lt;/p&gt;

&lt;p&gt;It is a masterful piece of security architecture that proves we don't need to invent new math to solve complex problems; we just need to orchestrate the math we have more intelligently.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What are your thoughts on asymmetric offline 2FA?&lt;/strong&gt; Do you think the Honey-Pulse mechanism should become a standard feature in all modern authentication apps? Let's discuss in the comments below! 👇&lt;/p&gt;

</description>
      <category>security</category>
      <category>cryptography</category>
      <category>totp</category>
    </item>
    <item>
      <title>Beyond Passkeys and OTP: Why I Built a Protocol for the Authentication Gaps We Keep Ignoring</title>
      <dc:creator>Hossein Hezami</dc:creator>
      <pubDate>Thu, 23 Jul 2026 20:09:09 +0000</pubDate>
      <link>https://dev.to/hosseinhezami/beyond-passkeys-and-otp-why-i-built-a-protocol-for-the-authentication-gaps-we-keep-ignoring-18m4</link>
      <guid>https://dev.to/hosseinhezami/beyond-passkeys-and-otp-why-i-built-a-protocol-for-the-authentication-gaps-we-keep-ignoring-18m4</guid>
      <description>&lt;p&gt;Passkeys are winning the browser login race.&lt;/p&gt;

&lt;p&gt;And they should.&lt;/p&gt;

&lt;p&gt;WebAuthn and FIDO2 solved a huge part of the authentication problem: phishing-resistant, browser-native, public-key authentication.&lt;/p&gt;

&lt;p&gt;But the more I worked on real systems, the more I noticed a gap.&lt;/p&gt;

&lt;p&gt;Not every authentication problem happens inside a browser.&lt;/p&gt;

&lt;p&gt;Some happen on a point-of-sale terminal.&lt;/p&gt;

&lt;p&gt;Some happen offline.&lt;/p&gt;

&lt;p&gt;Some happen inside a legacy OTP form that cannot be rewritten overnight.&lt;/p&gt;

&lt;p&gt;Some happen during a high-value transaction where the user must visually confirm an amount.&lt;/p&gt;

&lt;p&gt;Some happen under coercion.&lt;/p&gt;

&lt;p&gt;And some require approval from more than one device.&lt;/p&gt;

&lt;p&gt;That is the gap that led me to &lt;strong&gt;PulseProof Sentinel Protocol&lt;/strong&gt;, or &lt;strong&gt;PPS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;PPS is an experimental open authentication protocol that replaces shared-secret TOTP-style codes with signed, time-bound, asymmetric proofs called &lt;strong&gt;Pulses&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can explore the project here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io" rel="noopener noreferrer"&gt;https://pps-protocol.github.io&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem With TOTP
&lt;/h2&gt;

&lt;p&gt;TOTP is everywhere.&lt;/p&gt;

&lt;p&gt;It is simple, widely supported, and easy to deploy.&lt;/p&gt;

&lt;p&gt;But it has a structural weakness:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;code = HMAC(shared_secret, time)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server knows the secret.&lt;/p&gt;

&lt;p&gt;If the server database is breached, the attacker can generate valid codes.&lt;/p&gt;

&lt;p&gt;That is not ideal.&lt;/p&gt;

&lt;p&gt;Public-key authentication solves this. The server should not need to know the secret that proves identity.&lt;/p&gt;

&lt;p&gt;That is the core idea behind PPS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pulse = Sign(private_key, time + rp + nonce + counter + context + policy)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user’s device holds the private key.&lt;/p&gt;

&lt;p&gt;The server stores only the public key.&lt;/p&gt;

&lt;p&gt;The proof is signed, time-bound, replay-protected, and bound to the relying party.&lt;/p&gt;




&lt;h2&gt;
  
  
  PPS Is Not a WebAuthn Replacement
&lt;/h2&gt;

&lt;p&gt;This is important.&lt;/p&gt;

&lt;p&gt;PPS is not trying to replace WebAuthn.&lt;/p&gt;

&lt;p&gt;If you are building browser-based passwordless login, WebAuthn is usually the right answer.&lt;/p&gt;

&lt;p&gt;PPS is designed to complement WebAuthn.&lt;/p&gt;

&lt;p&gt;It targets the operational gaps where WebAuthn is unavailable, impractical, or insufficient:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;offline authentication&lt;/li&gt;
&lt;li&gt;legacy OTP input forms&lt;/li&gt;
&lt;li&gt;QR-code and deep-link authentication&lt;/li&gt;
&lt;li&gt;constrained hardware terminals&lt;/li&gt;
&lt;li&gt;point-of-sale and IoT devices&lt;/li&gt;
&lt;li&gt;human-visible transaction confirmation&lt;/li&gt;
&lt;li&gt;silent duress signaling&lt;/li&gt;
&lt;li&gt;offline multi-device threshold approval&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;WebAuthn is for passkeys.&lt;br&gt;&lt;br&gt;
PPS is for the authentication flows that still live outside the passkey world.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What Is a Pulse?
&lt;/h2&gt;

&lt;p&gt;A Pulse is a signed authentication statement.&lt;/p&gt;

&lt;p&gt;It can be bound to several things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a relying-party identifier&lt;/li&gt;
&lt;li&gt;a time epoch&lt;/li&gt;
&lt;li&gt;a server nonce&lt;/li&gt;
&lt;li&gt;a monotonic counter&lt;/li&gt;
&lt;li&gt;an expiration window&lt;/li&gt;
&lt;li&gt;a security policy&lt;/li&gt;
&lt;li&gt;a transaction hash&lt;/li&gt;
&lt;li&gt;environmental context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes PPS flexible.&lt;/p&gt;

&lt;p&gt;A Pulse can be used for simple login.&lt;/p&gt;

&lt;p&gt;It can also be used for transaction signing, offline terminal authentication, or multi-device approval.&lt;/p&gt;

&lt;p&gt;The protocol uses deterministic CBOR encoding and Ed25519 signatures.&lt;/p&gt;

&lt;p&gt;The mandatory profile is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PPS-ED25519-CBOR30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can read the full specification here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The documentation is available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/docs/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/docs/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The protocol is also submitted as an IETF Internet-Draft:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/" rel="noopener noreferrer"&gt;https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Developer Story: PHP and Laravel
&lt;/h2&gt;

&lt;p&gt;A protocol is only useful if people can implement it.&lt;/p&gt;

&lt;p&gt;That is why the first sample implementation is available in PHP.&lt;/p&gt;

&lt;p&gt;The core package is framework-agnostic:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pps-protocol/pps-php" rel="noopener noreferrer"&gt;https://github.com/pps-protocol/pps-php&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can install it with Composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require pps-protocol/pps-php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Package website:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pps-php/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pps-php/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pps-php/docs/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pps-php/docs/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Packagist:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://packagist.org/packages/pps-protocol/pps-php" rel="noopener noreferrer"&gt;https://packagist.org/packages/pps-protocol/pps-php&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Laravel applications, there is a dedicated integration package:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pps-protocol/laravel-pps" rel="noopener noreferrer"&gt;https://github.com/pps-protocol/laravel-pps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require pps-protocol/laravel-pps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan pps:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Laravel package provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;service provider&lt;/li&gt;
&lt;li&gt;publishable configuration&lt;/li&gt;
&lt;li&gt;API routes&lt;/li&gt;
&lt;li&gt;HTTP controller&lt;/li&gt;
&lt;li&gt;facade&lt;/li&gt;
&lt;li&gt;Artisan commands&lt;/li&gt;
&lt;li&gt;storage backend integration&lt;/li&gt;
&lt;li&gt;transaction challenge endpoints&lt;/li&gt;
&lt;li&gt;silent duress handling support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Laravel package website:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/laravel-pps/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/laravel-pps/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Packagist:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://packagist.org/packages/pps-protocol/laravel-pps" rel="noopener noreferrer"&gt;https://packagist.org/packages/pps-protocol/laravel-pps&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  A Small Example
&lt;/h2&gt;

&lt;p&gt;At the protocol level, the idea is simple.&lt;/p&gt;

&lt;p&gt;The client signs a Pulse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pps\Client\AuthenticatorClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthenticatorClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$clientState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$pulse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;rpId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'example.com'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$nonceFromServer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createPulse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server verifies it using the stored public key.&lt;/p&gt;

&lt;p&gt;No shared OTP secret is required.&lt;/p&gt;

&lt;p&gt;In Laravel, the package exposes endpoints such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET  /pps/health
GET  /pps/challenge
POST /pps/register
POST /pps/verify
POST /pps/transaction/challenge
POST /pps/transaction/verify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it easy to integrate PPS into an existing authentication or transaction-signing flow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Transaction Signing Is Where PPS Becomes Interesting
&lt;/h2&gt;

&lt;p&gt;One of my favorite PPS features is transaction signing.&lt;/p&gt;

&lt;p&gt;Imagine a withdrawal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Amount: 2,500,067 IRR
Trust Code: 49371867
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last two digits of the Trust Code come from the transaction amount.&lt;/p&gt;

&lt;p&gt;This creates a human-visible connection between the cryptographic proof and the transaction being approved.&lt;/p&gt;

&lt;p&gt;The user can confirm:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes, the code I see matches the amount I requested.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;banking&lt;/li&gt;
&lt;li&gt;fintech&lt;/li&gt;
&lt;li&gt;crypto withdrawals&lt;/li&gt;
&lt;li&gt;admin approvals&lt;/li&gt;
&lt;li&gt;high-value payments&lt;/li&gt;
&lt;li&gt;corporate treasury flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PPS can bind the transaction hash, amount, session, and policy into the signed Pulse.&lt;/p&gt;

&lt;p&gt;That is much stronger than sending a generic OTP code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Silent Duress: Authentication Under Coercion
&lt;/h2&gt;

&lt;p&gt;Another important area is duress.&lt;/p&gt;

&lt;p&gt;What happens if someone is forced to authenticate?&lt;/p&gt;

&lt;p&gt;Traditional OTP systems do not have a good answer.&lt;/p&gt;

&lt;p&gt;PPS introduces an optional duress mechanism.&lt;/p&gt;

&lt;p&gt;The user can authenticate with a hidden duress key.&lt;/p&gt;

&lt;p&gt;The resulting Pulse is cryptographically valid, but the server recognizes it as a &lt;strong&gt;Honey-Pulse&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The server can return a normal-looking success response while internally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;restricting account capabilities&lt;/li&gt;
&lt;li&gt;blocking high-value operations&lt;/li&gt;
&lt;li&gt;delaying settlement&lt;/li&gt;
&lt;li&gt;triggering a silent alert&lt;/li&gt;
&lt;li&gt;preserving audit logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is sensitive territory, and implementation matters a lot.&lt;/p&gt;

&lt;p&gt;But for high-risk accounts, it is a powerful concept.&lt;/p&gt;




&lt;h2&gt;
  
  
  Offline and Multi-Device Flows
&lt;/h2&gt;

&lt;p&gt;PPS also supports offline authentication.&lt;/p&gt;

&lt;p&gt;Because a Pulse is signed and time-bound, it can be generated without a live network round-trip.&lt;/p&gt;

&lt;p&gt;Offline mode requires stricter rate limiting and careful operational design, but it is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;terminals&lt;/li&gt;
&lt;li&gt;IoT devices&lt;/li&gt;
&lt;li&gt;field equipment&lt;/li&gt;
&lt;li&gt;unstable networks&lt;/li&gt;
&lt;li&gt;emergency access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PPS also supports offline multi-device threshold approval.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2-of-2: phone + watch
2-of-3: phone + laptop + hardware key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful when a single device should not be enough to approve a sensitive action.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Ecosystem
&lt;/h2&gt;

&lt;p&gt;The PPS project is organized under a GitHub organization:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pps-protocol" rel="noopener noreferrer"&gt;https://github.com/pps-protocol&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main repositories are:&lt;/p&gt;

&lt;h3&gt;
  
  
  PulseProof Sentinel Protocol
&lt;/h3&gt;

&lt;p&gt;The specification repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pps-protocol/pulseproof-sentinel" rel="noopener noreferrer"&gt;https://github.com/pps-protocol/pulseproof-sentinel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Website:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Specification:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/docs/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/docs/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  pps-php
&lt;/h3&gt;

&lt;p&gt;The core PHP implementation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pps-protocol/pps-php" rel="noopener noreferrer"&gt;https://github.com/pps-protocol/pps-php&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Website:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pps-php/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pps-php/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pps-php/docs/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pps-php/docs/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Packagist:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://packagist.org/packages/pps-protocol/pps-php" rel="noopener noreferrer"&gt;https://packagist.org/packages/pps-protocol/pps-php&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  laravel-pps
&lt;/h3&gt;

&lt;p&gt;The Laravel integration package.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pps-protocol/laravel-pps" rel="noopener noreferrer"&gt;https://github.com/pps-protocol/laravel-pps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Website:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/laravel-pps/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/laravel-pps/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Packagist:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://packagist.org/packages/pps-protocol/laravel-pps" rel="noopener noreferrer"&gt;https://packagist.org/packages/pps-protocol/laravel-pps&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Explore PPS?
&lt;/h2&gt;

&lt;p&gt;PPS is experimental.&lt;/p&gt;

&lt;p&gt;It has not been independently audited.&lt;/p&gt;

&lt;p&gt;It is not ready to replace your production authentication system tomorrow.&lt;/p&gt;

&lt;p&gt;But if you care about authentication design, it is worth exploring.&lt;/p&gt;

&lt;p&gt;It is especially interesting if you are working on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fintech authentication&lt;/li&gt;
&lt;li&gt;crypto exchange security&lt;/li&gt;
&lt;li&gt;offline device login&lt;/li&gt;
&lt;li&gt;POS terminals&lt;/li&gt;
&lt;li&gt;IoT authentication&lt;/li&gt;
&lt;li&gt;transaction signing&lt;/li&gt;
&lt;li&gt;high-value approval workflows&lt;/li&gt;
&lt;li&gt;duress-aware accounts&lt;/li&gt;
&lt;li&gt;multi-device authorization&lt;/li&gt;
&lt;li&gt;legacy OTP migration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PPS asks a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why should the server ever store a shared OTP secret when it can verify a signature instead?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Start Here
&lt;/h2&gt;

&lt;p&gt;The best place to start is the project website:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io" rel="noopener noreferrer"&gt;https://pps-protocol.github.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then read the specification:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are a PHP developer, try the core package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require pps-protocol/pps-php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are using Laravel, install the Laravel integration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require pps-protocol/laravel-pps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you are interested in protocol design, review the IETF Internet-Draft:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/" rel="noopener noreferrer"&gt;https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PPS is early, experimental, and open for feedback.&lt;/p&gt;

&lt;p&gt;If you believe authentication should move beyond shared secrets, give it a look.&lt;/p&gt;

</description>
      <category>authentication</category>
      <category>security</category>
      <category>totp</category>
      <category>php</category>
    </item>
    <item>
      <title>TOTP Secrets Are a Liability: Meet PPS, an Asymmetric Authentication Protocol for PHP and Laravel</title>
      <dc:creator>Hossein Hezami</dc:creator>
      <pubDate>Thu, 23 Jul 2026 20:01:37 +0000</pubDate>
      <link>https://dev.to/hosseinhezami/totp-secrets-are-a-liability-meet-pps-an-asymmetric-authentication-protocol-for-php-and-laravel-31ic</link>
      <guid>https://dev.to/hosseinhezami/totp-secrets-are-a-liability-meet-pps-an-asymmetric-authentication-protocol-for-php-and-laravel-31ic</guid>
      <description>&lt;p&gt;Most two-factor authentication systems still rely on a dangerous assumption:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the server is breached, authentication secrets can be protected.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;TOTP breaks that assumption.&lt;/p&gt;

&lt;p&gt;With TOTP, the server stores a shared secret. If your database leaks, attackers can generate valid OTP codes.&lt;/p&gt;

&lt;p&gt;That is exactly the problem &lt;strong&gt;PulseProof Sentinel Protocol&lt;/strong&gt;, or &lt;strong&gt;PPS&lt;/strong&gt;, tries to solve.&lt;/p&gt;

&lt;p&gt;PPS is an experimental open authentication protocol that replaces shared-secret TOTP codes with signed, time-bound, asymmetric proofs called &lt;strong&gt;Pulses&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TOTP:
  code = HMAC(shared_secret, time)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PPS uses this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PPS:
  Pulse = Sign(private_key, time + rp + nonce + counter + context + policy)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server never stores a shared OTP secret.&lt;/p&gt;

&lt;p&gt;It stores only public keys.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is PPS?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;PulseProof Sentinel Protocol&lt;/strong&gt; is an asymmetric authentication protocol designed for scenarios where traditional OTP, push authentication, and even WebAuthn are not enough.&lt;/p&gt;

&lt;p&gt;It is especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;offline authentication&lt;/li&gt;
&lt;li&gt;legacy OTP input forms&lt;/li&gt;
&lt;li&gt;QR-code and deep-link login&lt;/li&gt;
&lt;li&gt;constrained hardware terminals&lt;/li&gt;
&lt;li&gt;point-of-sale and IoT devices&lt;/li&gt;
&lt;li&gt;transaction signing with human-visible confirmation&lt;/li&gt;
&lt;li&gt;silent duress signaling&lt;/li&gt;
&lt;li&gt;offline multi-device threshold approval&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PPS is not trying to replace WebAuthn/FIDO2.&lt;/p&gt;

&lt;p&gt;WebAuthn remains the preferred standard for browser-based passkey authentication.&lt;/p&gt;

&lt;p&gt;PPS is designed to &lt;strong&gt;complement&lt;/strong&gt; WebAuthn by covering operational gaps where WebAuthn is unavailable or impractical.&lt;/p&gt;

&lt;p&gt;You can explore the protocol here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project website: &lt;a href="https://pps-protocol.github.io" rel="noopener noreferrer"&gt;https://pps-protocol.github.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Specification: &lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Documentation: &lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/docs/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/docs/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;IETF Internet-Draft: &lt;a href="https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/" rel="noopener noreferrer"&gt;https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub organization: &lt;a href="https://github.com/pps-protocol" rel="noopener noreferrer"&gt;https://github.com/pps-protocol&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Not Just Use WebAuthn?
&lt;/h2&gt;

&lt;p&gt;WebAuthn is excellent.&lt;/p&gt;

&lt;p&gt;If you are building browser-based passwordless authentication, use WebAuthn.&lt;/p&gt;

&lt;p&gt;But many real systems still need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- OTP-style input fields
- offline verification
- hardware terminals without browser support
- transaction amount confirmation
- silent duress codes
- multi-device approval
- QR/deep-link authentication flows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is where PPS fits.&lt;/p&gt;

&lt;p&gt;Think of it like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Browser passkey login&lt;/td&gt;
&lt;td&gt;WebAuthn/FIDO2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legacy OTP form&lt;/td&gt;
&lt;td&gt;PPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Offline terminal authentication&lt;/td&gt;
&lt;td&gt;PPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High-value transaction signing&lt;/td&gt;
&lt;td&gt;PPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Silent duress authentication&lt;/td&gt;
&lt;td&gt;PPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-device approval&lt;/td&gt;
&lt;td&gt;PPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IoT or constrained device authentication&lt;/td&gt;
&lt;td&gt;PPS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Core Features
&lt;/h2&gt;

&lt;p&gt;PPS includes a small core protocol plus optional advanced modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ed25519 signatures&lt;/li&gt;
&lt;li&gt;deterministic CBOR encoding&lt;/li&gt;
&lt;li&gt;time-bound Pulses&lt;/li&gt;
&lt;li&gt;nonce binding&lt;/li&gt;
&lt;li&gt;monotonic counter replay protection&lt;/li&gt;
&lt;li&gt;relying-party binding&lt;/li&gt;
&lt;li&gt;expiration enforcement&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Optional Advanced Modules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;forward-secure key ratcheting&lt;/li&gt;
&lt;li&gt;silent duress / Honey-Pulse signaling&lt;/li&gt;
&lt;li&gt;offline n-of-m threshold approval&lt;/li&gt;
&lt;li&gt;transaction AmountMark verification&lt;/li&gt;
&lt;li&gt;dynamic policy binding&lt;/li&gt;
&lt;li&gt;environmental context binding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The protocol specification is available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The PHP Implementation: &lt;code&gt;pps-php&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The core PHP implementation is available as a framework-agnostic package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pps-protocol/pps-php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/pps-protocol/pps-php" rel="noopener noreferrer"&gt;https://github.com/pps-protocol/pps-php&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Website: &lt;a href="https://pps-protocol.github.io/pps-php/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pps-php/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Documentation: &lt;a href="https://pps-protocol.github.io/pps-php/docs/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pps-php/docs/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Packagist: &lt;a href="https://packagist.org/packages/pps-protocol/pps-php" rel="noopener noreferrer"&gt;https://packagist.org/packages/pps-protocol/pps-php&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install it with Composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require pps-protocol/pps-php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pulse creation&lt;/li&gt;
&lt;li&gt;Pulse verification&lt;/li&gt;
&lt;li&gt;registration flows&lt;/li&gt;
&lt;li&gt;Trust Code generation&lt;/li&gt;
&lt;li&gt;AmountMark transaction codes&lt;/li&gt;
&lt;li&gt;duress keys&lt;/li&gt;
&lt;li&gt;threshold signatures&lt;/li&gt;
&lt;li&gt;offline mode&lt;/li&gt;
&lt;li&gt;memory, file, PDO, and Redis storage backends&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Example: Creating a Pulse
&lt;/h2&gt;

&lt;p&gt;Here is a simplified client-side example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pps\Client\AuthenticatorClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthenticatorClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$clientState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$pulse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;rpId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'example.com'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$nonceFromServer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createPulse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$pulse&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'token'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$pulse&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'trust_code'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server verifies the Pulse using only the stored public key.&lt;/p&gt;

&lt;p&gt;No shared secret is required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Laravel Integration: &lt;code&gt;laravel-pps&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If you are using Laravel, there is a dedicated integration package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pps-protocol/laravel-pps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/pps-protocol/laravel-pps" rel="noopener noreferrer"&gt;https://github.com/pps-protocol/laravel-pps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Website: &lt;a href="https://pps-protocol.github.io/laravel-pps/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/laravel-pps/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Packagist: &lt;a href="https://packagist.org/packages/pps-protocol/laravel-pps" rel="noopener noreferrer"&gt;https://packagist.org/packages/pps-protocol/laravel-pps&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require pps-protocol/laravel-pps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan pps:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This publishes the PPS config and migrations.&lt;/p&gt;

&lt;p&gt;The package provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;service provider&lt;/li&gt;
&lt;li&gt;publishable configuration&lt;/li&gt;
&lt;li&gt;API routes&lt;/li&gt;
&lt;li&gt;HTTP controller&lt;/li&gt;
&lt;li&gt;facade&lt;/li&gt;
&lt;li&gt;Artisan commands&lt;/li&gt;
&lt;li&gt;storage backend integration&lt;/li&gt;
&lt;li&gt;transaction challenge endpoints&lt;/li&gt;
&lt;li&gt;silent duress handling support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Default routes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/pps/health&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Health check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/pps/challenge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create authentication challenge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/pps/register&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Register a device&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/pps/verify&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Verify a Pulse Token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/pps/transaction/challenge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create transaction challenge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/pps/transaction/verify&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Verify transaction-bound Pulse&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Test the health endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8000/pps/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PulseProof Sentinel Protocol"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"algorithm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PPS-ED25519-CBOR30"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"epoch_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rp_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Transaction Signing With AmountMark
&lt;/h2&gt;

&lt;p&gt;One of the most useful PPS features is transaction signing.&lt;/p&gt;

&lt;p&gt;Imagine a withdrawal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Amount: 2,500,067 IRR
Trust Code: 49371867
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last two digits, &lt;code&gt;67&lt;/code&gt;, are derived from the transaction amount.&lt;/p&gt;

&lt;p&gt;This allows the user to visually confirm that the signed transaction matches the displayed amount.&lt;/p&gt;

&lt;p&gt;The client binds the transaction hash and amount to the Pulse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pps\Crypto\Base64Url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pps\Payload\ContextObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ContextObject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$context&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;sessionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Base64Url&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$sessionId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$context&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;txHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Base64Url&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$txHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$pulse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;rpId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'example.com'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$nonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;amountMinor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2500067&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createPulse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server verifies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;signature&lt;/li&gt;
&lt;li&gt;nonce&lt;/li&gt;
&lt;li&gt;counter&lt;/li&gt;
&lt;li&gt;transaction hash&lt;/li&gt;
&lt;li&gt;amount mark&lt;/li&gt;
&lt;li&gt;Trust Code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is much stronger than sending a plain OTP for transaction confirmation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Silent Duress Authentication
&lt;/h2&gt;

&lt;p&gt;PPS also supports silent duress signaling.&lt;/p&gt;

&lt;p&gt;If a user is forced to authenticate, the client can sign with a hidden duress key.&lt;/p&gt;

&lt;p&gt;The server detects this internally but returns a normal-looking success response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;honey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Return normal response.&lt;/span&gt;
    &lt;span class="c1"&gt;// Internally restrict account, alert security, delay settlement, etc.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful for fintech, banking, crypto exchanges, and high-risk accounts.&lt;/p&gt;

&lt;p&gt;The outward response should remain indistinguishable from a normal login.&lt;/p&gt;




&lt;h2&gt;
  
  
  How PPS Compares to TOTP
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;TOTP&lt;/th&gt;
&lt;th&gt;PPS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Shared secret on server&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Asymmetric proof&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Offline capable&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legacy OTP form support&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transaction binding&lt;/td&gt;
&lt;td&gt;Weak&lt;/td&gt;
&lt;td&gt;Strong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amount confirmation&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Silent duress&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Threshold approval&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Policy binding&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context binding&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Important Links
&lt;/h2&gt;

&lt;p&gt;Here are the most important links if you want to explore PPS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project website: &lt;a href="https://pps-protocol.github.io" rel="noopener noreferrer"&gt;https://pps-protocol.github.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Protocol repository: &lt;a href="https://github.com/pps-protocol/pulseproof-sentinel" rel="noopener noreferrer"&gt;https://github.com/pps-protocol/pulseproof-sentinel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Specification: &lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Documentation: &lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/docs/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/docs/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;IETF Internet-Draft: &lt;a href="https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/" rel="noopener noreferrer"&gt;https://datatracker.ietf.org/doc/draft-hezami-pulseproof-sentinel/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PHP core package: &lt;a href="https://github.com/pps-protocol/pps-php" rel="noopener noreferrer"&gt;https://github.com/pps-protocol/pps-php&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PHP package docs: &lt;a href="https://pps-protocol.github.io/pps-php/docs/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pps-php/docs/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Laravel package: &lt;a href="https://github.com/pps-protocol/laravel-pps" rel="noopener noreferrer"&gt;https://github.com/pps-protocol/laravel-pps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Laravel package website: &lt;a href="https://pps-protocol.github.io/laravel-pps/" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/laravel-pps/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Packagist core package: &lt;a href="https://packagist.org/packages/pps-protocol/pps-php" rel="noopener noreferrer"&gt;https://packagist.org/packages/pps-protocol/pps-php&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Packagist Laravel package: &lt;a href="https://packagist.org/packages/pps-protocol/laravel-pps" rel="noopener noreferrer"&gt;https://packagist.org/packages/pps-protocol/laravel-pps&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;If you are building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fintech authentication&lt;/li&gt;
&lt;li&gt;crypto withdrawal confirmation&lt;/li&gt;
&lt;li&gt;offline device authentication&lt;/li&gt;
&lt;li&gt;POS or IoT login&lt;/li&gt;
&lt;li&gt;high-security admin approval&lt;/li&gt;
&lt;li&gt;duress-aware accounts&lt;/li&gt;
&lt;li&gt;multi-device authorization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PPS may be worth exploring.&lt;/p&gt;

&lt;p&gt;Start with the website:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io" rel="noopener noreferrer"&gt;https://pps-protocol.github.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then read the specification:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html" rel="noopener noreferrer"&gt;https://pps-protocol.github.io/pulseproof-sentinel/SPEC.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you use PHP or Laravel, install the packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require pps-protocol/pps-php
composer require pps-protocol/laravel-pps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PPS is experimental, so it is not recommended for production without security review. But if you are interested in authentication protocols, asymmetric OTP alternatives, or transaction signing, it is definitely worth a look.&lt;/p&gt;

&lt;p&gt;If you find the idea useful, star the repositories, test the packages, and share feedback.&lt;/p&gt;

&lt;p&gt;GitHub organization:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pps-protocol" rel="noopener noreferrer"&gt;https://github.com/pps-protocol&lt;/a&gt;&lt;/p&gt;

</description>
      <category>authentication</category>
      <category>security</category>
      <category>php</category>
      <category>laravel</category>
    </item>
    <item>
      <title>Master Role-Based Access Control with Laravel Permission Manager</title>
      <dc:creator>Hossein Hezami</dc:creator>
      <pubDate>Wed, 24 Sep 2025 14:33:20 +0000</pubDate>
      <link>https://dev.to/hosseinhezami/master-role-based-access-control-with-laravel-permission-manager-4nc3</link>
      <guid>https://dev.to/hosseinhezami/master-role-based-access-control-with-laravel-permission-manager-4nc3</guid>
      <description>&lt;p&gt;Building a secure, scalable Laravel application often requires a robust permission management system. Enter &lt;strong&gt;Laravel Permission Manager&lt;/strong&gt;, a powerful package designed to streamline role-based access control (RBAC) with a flexible, feature-rich API. Whether you're securing routes, managing roles, or integrating permissions into your Blade templates, this package has you covered. In this post, I'll walk you through its installation, configuration, and usage to help you implement a bulletproof RBAC system in your Laravel app.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Laravel Permission Manager?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://packagist.org/packages/hosseinhezami/laravel-permission-manager" rel="noopener noreferrer"&gt;Laravel Permission Manager&lt;/a&gt; package, developed by Hossein Hezami, offers a comprehensive solution for managing roles and permissions in Laravel applications. Here’s what makes it stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role-Based Access Control (RBAC)&lt;/strong&gt;: Assign multiple roles to users and permissions to roles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wildcard Permissions&lt;/strong&gt;: Support for flexible route matching (e.g., &lt;code&gt;admin.*&lt;/code&gt;, &lt;code&gt;*admin*&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blade Directives&lt;/strong&gt;: Easily check roles and permissions in templates with &lt;code&gt;@hasRole&lt;/code&gt; and &lt;code&gt;@hasPermission&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artisan Commands&lt;/strong&gt;: Manage roles and permissions from the command line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facade Methods&lt;/strong&gt;: Programmatically handle roles and permissions with a fluent API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Middleware Support&lt;/strong&gt;: Protect routes with role or permission checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: Boost performance with permission caching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Guard Support&lt;/strong&gt;: Works seamlessly with Laravel’s authentication guards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export/Import&lt;/strong&gt;: Save and restore roles/permissions as JSON.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ready to get started? Let’s dive into the setup and usage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Installing Laravel Permission Manager is straightforward with Composer. Follow these steps to integrate it into your Laravel project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install the Package&lt;/strong&gt;
Run the following command to install the package:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   composer require hosseinhezami/laravel-permission-manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Register the Service Provider (Optional)&lt;/strong&gt;
If Laravel’s package auto-discovery is disabled, add the service provider and facade to &lt;code&gt;config/app.php&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;   &lt;span class="s1"&gt;'providers'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
       &lt;span class="c1"&gt;// ...&lt;/span&gt;
       &lt;span class="nc"&gt;HosseinHezami\PermissionManager\PermissionManagerServiceProvider&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s1"&gt;'aliases'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
       &lt;span class="c1"&gt;// ...&lt;/span&gt;
       &lt;span class="s1"&gt;'PermissionManager'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;HosseinHezami\PermissionManager\Facades\PermissionManager&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Publish Configuration and Migrations&lt;/strong&gt;
Publish the configuration file and migrations to set up the package:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   php artisan vendor:publish &lt;span class="nt"&gt;--provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"HosseinHezami&lt;/span&gt;&lt;span class="se"&gt;\P&lt;/span&gt;&lt;span class="s2"&gt;ermissionManager&lt;/span&gt;&lt;span class="se"&gt;\P&lt;/span&gt;&lt;span class="s2"&gt;ermissionManagerServiceProvider"&lt;/span&gt; &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"config"&lt;/span&gt;
   php artisan vendor:publish &lt;span class="nt"&gt;--provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"HosseinHezami&lt;/span&gt;&lt;span class="se"&gt;\P&lt;/span&gt;&lt;span class="s2"&gt;ermissionManager&lt;/span&gt;&lt;span class="se"&gt;\P&lt;/span&gt;&lt;span class="s2"&gt;ermissionManagerServiceProvider"&lt;/span&gt; &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"migrations"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run Migrations&lt;/strong&gt;
Create the necessary database tables for roles and permissions:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add the Permission Trait&lt;/strong&gt;
Add the &lt;code&gt;PermissionTrait&lt;/code&gt; to your &lt;code&gt;User&lt;/code&gt; model:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;   &lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Models&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HosseinHezami\PermissionManager\Traits\PermissionTrait&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Foundation\Auth\User&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;Authenticatable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Authenticatable&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PermissionTrait&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run the Install Command&lt;/strong&gt;
For a streamlined setup, use the Artisan install command. Here are some variations:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="c"&gt;# Basic installation&lt;/span&gt;
   php artisan permission-manager:install

   &lt;span class="c"&gt;# Install and run migrations&lt;/span&gt;
   php artisan permission-manager:install &lt;span class="nt"&gt;--migrate&lt;/span&gt;

   &lt;span class="c"&gt;# Install, run migrations, and overwrite existing files&lt;/span&gt;
   php artisan permission-manager:install &lt;span class="nt"&gt;--migrate&lt;/span&gt; &lt;span class="nt"&gt;--force&lt;/span&gt;

   &lt;span class="c"&gt;# Install with a custom User model path&lt;/span&gt;
   php artisan permission-manager:install &lt;span class="nt"&gt;--user-model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/path/to/User.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;After publishing the configuration, you can customize the package in &lt;code&gt;config/permission-manager.php&lt;/code&gt;. Here’s a sample configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'models'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'role'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;\HosseinHezami\PermissionManager\Models\Role&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'permission'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;\HosseinHezami\PermissionManager\Models\Permission&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'user'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;\App\Models\User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'tables'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'roles'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'roles'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'permissions'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'permissions'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'role_permissions'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'role_permissions'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'user_roles'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'user_roles'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'cache_duration'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Cache permissions for 60 minutes&lt;/span&gt;
    &lt;span class="s1"&gt;'log_denials'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Log permission/role denials&lt;/span&gt;
    &lt;span class="s1"&gt;'wildcards'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Enable wildcard support&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file lets you tweak model classes, table names, caching duration, and wildcard support to suit your application’s needs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Database Migrations
&lt;/h2&gt;

&lt;p&gt;The package creates four tables to manage roles and permissions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;roles&lt;/code&gt;&lt;/strong&gt;: Stores role details (name, slug, description).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;permissions&lt;/code&gt;&lt;/strong&gt;: Stores permission routes (e.g., &lt;code&gt;users.edit&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;role_permissions&lt;/code&gt;&lt;/strong&gt;: Links roles to permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;user_roles&lt;/code&gt;&lt;/strong&gt;: Links users to roles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The migrations are automatically published when you run the &lt;code&gt;vendor:publish&lt;/code&gt; command for the &lt;code&gt;migrations&lt;/code&gt; tag.&lt;/p&gt;




&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Let’s explore how to leverage Laravel Permission Manager in your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Blade Directives
&lt;/h3&gt;

&lt;p&gt;Control access in your Blade templates with intuitive directives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@hasRole('admin')
    &amp;lt;p&amp;gt;Welcome, Admin!&amp;lt;/p&amp;gt;
@endhasRole

@hasPermission('users.edit')
    &amp;lt;a href="/users/edit"&amp;gt;Edit User&amp;lt;/a&amp;gt;
@endhasPermission
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These directives make it easy to show or hide content based on roles or permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Middleware
&lt;/h3&gt;

&lt;p&gt;Protect routes with middleware for roles or permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/admin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;AdminController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'index'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pm:role:admin|manager'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/posts'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;PostController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'create'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pm:permission:posts|post.create'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;pm&lt;/code&gt; middleware ensures only users with the specified roles or permissions can access the route.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Artisan Commands
&lt;/h3&gt;

&lt;p&gt;Manage roles and permissions directly from the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List roles and permissions&lt;/span&gt;
php artisan roles:list
php artisan permissions:list

&lt;span class="c"&gt;# Create a role&lt;/span&gt;
php artisan role:create admin &lt;span class="s2"&gt;"Administrator"&lt;/span&gt; &lt;span class="s2"&gt;"Has full system access"&lt;/span&gt;

&lt;span class="c"&gt;# Update a role&lt;/span&gt;
php artisan role:update admin &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Super Admin"&lt;/span&gt; &lt;span class="nt"&gt;--description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Updated description"&lt;/span&gt;

&lt;span class="c"&gt;# Delete a role&lt;/span&gt;
php artisan role:delete admin

&lt;span class="c"&gt;# Create permissions&lt;/span&gt;
php artisan permission:create &lt;span class="s2"&gt;"users.*"&lt;/span&gt;
php artisan permission:create &lt;span class="s2"&gt;"users.create,users.edit"&lt;/span&gt;

&lt;span class="c"&gt;# Sync routes with permissions&lt;/span&gt;
php artisan permission:sync-routes

&lt;span class="c"&gt;# Assign/revoke permissions to a role&lt;/span&gt;
php artisan role:assign-permission admin &lt;span class="s2"&gt;"users.*"&lt;/span&gt;
php artisan role:revoke-permission admin &lt;span class="s2"&gt;"users.edit"&lt;/span&gt;

&lt;span class="c"&gt;# Assign/revoke roles to a user&lt;/span&gt;
php artisan user:assign-role 1 admin
php artisan user:revoke-role 1 admin

&lt;span class="c"&gt;# Export/import roles&lt;/span&gt;
php artisan role:export roles.json
php artisan role:import roles.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands make it easy to manage your RBAC system without writing code.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Facade Methods
&lt;/h3&gt;

&lt;p&gt;For programmatic control, use the &lt;code&gt;PermissionManager&lt;/code&gt; facade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HosseinHezami\PermissionManager\Facades\PermissionManager&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create a role&lt;/span&gt;
&lt;span class="nc"&gt;PermissionManager&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'slug'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Administrator'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Has full system access'&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Assign permissions to a role&lt;/span&gt;
&lt;span class="nc"&gt;PermissionManager&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;role&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assignPermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users.edit'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Assign a role to a user&lt;/span&gt;
&lt;span class="nc"&gt;PermissionManager&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assignRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Check permissions&lt;/span&gt;
&lt;span class="nv"&gt;$hasPermission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PermissionManager&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasPermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users.edit'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Wildcard Permissions
&lt;/h3&gt;

&lt;p&gt;Wildcard permissions add flexibility to route matching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Match all routes starting with 'admin'&lt;/span&gt;
&lt;span class="nc"&gt;PermissionManager&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'admin.*'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Match all routes containing 'admin'&lt;/span&gt;
&lt;span class="nc"&gt;PermissionManager&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'*admin*'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Trait Methods
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;PermissionTrait&lt;/code&gt; adds convenient methods to your &lt;code&gt;User&lt;/code&gt; model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Assign a role&lt;/span&gt;
&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assignRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Check permissions&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasPermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users.edit'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Allow edit action&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Descriptive Slugs&lt;/strong&gt;: Choose clear, meaningful slugs for roles and permissions (e.g., &lt;code&gt;users.edit&lt;/code&gt; instead of &lt;code&gt;edit&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage Wildcards&lt;/strong&gt;: Group related routes with wildcards (e.g., &lt;code&gt;users.*&lt;/code&gt; for all user-related actions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sync Routes Regularly&lt;/strong&gt;: Run &lt;code&gt;php artisan permission:sync-routes&lt;/code&gt; to keep permissions aligned with your routes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable Caching&lt;/strong&gt;: Set a reasonable &lt;code&gt;cache_duration&lt;/code&gt; in production to improve performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle Exceptions&lt;/strong&gt;: Use the package’s custom exceptions (e.g., &lt;code&gt;UnauthorizedException&lt;/code&gt;) for robust error handling.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Laravel Permission Manager&lt;/strong&gt; package is a game-changer for developers building secure Laravel applications. Its intuitive API, comprehensive Artisan commands, and flexible features like wildcard permissions and Blade directives make it a must-have for implementing RBAC. Whether you’re managing a small app or a large-scale system, this package simplifies access control without compromising on power.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://hosseinhezami.github.io/laravel-permission-manager" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; for more details, and feel free to contribute via the &lt;a href="https://github.com/hosseinhezami/laravel-permission-manager" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. Got questions? Reach out to the maintainer at &lt;a href="mailto:hossein.hezami@gmail.com"&gt;hossein.hezami@gmail.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What’s your favorite way to manage permissions in Laravel? Share your thoughts in the comments!&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>permission</category>
      <category>php</category>
      <category>acl</category>
    </item>
    <item>
      <title>Build Laravel AI Features in Minutes: A Guide to the Gemini Package</title>
      <dc:creator>Hossein Hezami</dc:creator>
      <pubDate>Fri, 12 Sep 2025 23:40:51 +0000</pubDate>
      <link>https://dev.to/hosseinhezami/build-laravel-ai-features-in-minutes-a-guide-to-the-gemini-package-2om5</link>
      <guid>https://dev.to/hosseinhezami/build-laravel-ai-features-in-minutes-a-guide-to-the-gemini-package-2om5</guid>
      <description>&lt;p&gt;Tired of reading docs and just want to see the code? Let's dive straight into how you can use the &lt;code&gt;hosseinhezami/laravel-gemini&lt;/code&gt; package to add powerful AI features to your Laravel application. The API is clean, fluent, and incredibly powerful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation &amp;amp; Setup
&lt;/h2&gt;

&lt;p&gt;First, get the package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require hosseinhezami/laravel-gemini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Publish the config file and set your API key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gemini-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .env
GEMINI_API_KEY=your_gemini_api_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code Examples: See It in Action
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Basic Text Generation &amp;amp; Chat
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;TextBuilder&lt;/code&gt; makes generating text or creating a chat interface simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HosseinHezami\LaravelGemini\Facades\Gemini&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Simple prompt&lt;/span&gt;
&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Gemini&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Write a tagline for a developer blog.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Chat with history&lt;/span&gt;
&lt;span class="nv"&gt;$history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'role'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'parts'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello!'&lt;/span&gt;&lt;span class="p"&gt;]]],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'role'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'model'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'parts'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hi there! How can I help?'&lt;/span&gt;&lt;span class="p"&gt;]]]&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Gemini&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'What’s the weather like?'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;history&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Structured Data Extraction
&lt;/h3&gt;

&lt;p&gt;Need consistent JSON output from a messy prompt? Use &lt;code&gt;structuredSchema&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Gemini&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;structuredSchema&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'properties'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'sentiment'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'enum'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'positive'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'negative'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'neutral'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'confidence'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'number'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'key_points'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'array'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'items'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="s1"&gt;'required'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'sentiment'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'The product is amazing but the delivery was late. I love the features though.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$analysis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// $analysis-&amp;gt;sentiment, $analysis-&amp;gt;key_points, etc.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Image Generation
&lt;/h3&gt;

&lt;p&gt;Generate images from a text description.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Gemini&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;image&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'A minimalist logo for a tech startup called "Nexus", using blue and green'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Save the generated image directly&lt;/span&gt;
&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app/logo.png'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Document Understanding
&lt;/h3&gt;

&lt;p&gt;Upload a file (PDF, DOC, image) and ask questions about it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// First, upload the file to Gemini's servers&lt;/span&gt;
&lt;span class="nv"&gt;$fileUri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Gemini&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;files&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'document'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$pathToInvoicePdf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Then, use it in a prompt&lt;/span&gt;
&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Gemini&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'document'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$pathToInvoicePdf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// or use the $fileUri&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'What is the total amount due on this invoice?'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Text-to-Speech (Audio)
&lt;/h3&gt;

&lt;p&gt;Generate spoken audio from text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Gemini&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Welcome to our application. We are thrilled to have you on board.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;voiceName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Kore'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Check docs for available voices&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// The package smartly handles the binary response,&lt;/span&gt;
&lt;span class="c1"&gt;// allowing you to save it directly.&lt;/span&gt;
&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;public_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'audio/welcome.mp3'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Real-Time Streaming
&lt;/h3&gt;

&lt;p&gt;Crucial for building chat interfaces that feel fast and responsive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In your controller (e.g., app/Http/Controllers/ChatController.php)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Gemini&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'gemini-2.5-flash-lite'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Use a fast model for streaming&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$chunk&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;connection_aborted&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"data: "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$text&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nb"&gt;ob_flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="nb"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'Content-Type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'text/event-stream'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'Cache-Control'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'no-cache'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'Connection'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'keep-alive'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'X-Accel-Buffering'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'no'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ready to Build?
&lt;/h2&gt;

&lt;p&gt;This is just the surface. The package also handles &lt;strong&gt;video generation&lt;/strong&gt;, &lt;strong&gt;embeddings&lt;/strong&gt;, and full &lt;strong&gt;file management&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For complete documentation, check out the official docs:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://hosseinhezami.github.io/laravel-gemini/" rel="noopener noreferrer"&gt;https://hosseinhezami.github.io/laravel-gemini/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hosseinhezami/laravel-gemini" rel="noopener noreferrer"&gt;https://github.com/hosseinhezami/laravel-gemini&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packagist.org/packages/hosseinhezami/laravel-gemini" rel="noopener noreferrer"&gt;https://packagist.org/packages/hosseinhezami/laravel-gemini&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What will you build first? Let me know in the comments! 👇&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>gemini</category>
      <category>ai</category>
      <category>api</category>
    </item>
    <item>
      <title>TOTP Authenticator: A Lightweight PHP Library for Secure Two-Factor Authentication</title>
      <dc:creator>Hossein Hezami</dc:creator>
      <pubDate>Fri, 05 Sep 2025 11:08:13 +0000</pubDate>
      <link>https://dev.to/hosseinhezami/totp-authenticator-a-lightweight-php-library-for-secure-two-factor-authentication-428p</link>
      <guid>https://dev.to/hosseinhezami/totp-authenticator-a-lightweight-php-library-for-secure-two-factor-authentication-428p</guid>
      <description>&lt;p&gt;Two-Factor Authentication (2FA) has become an essential layer of security for web applications, helping protect user accounts even if passwords are compromised. Among the most widely used 2FA methods is TOTP (Time-based One-Time Password), supported by popular apps like Google Authenticator, Authy, and Microsoft Authenticator.&lt;/p&gt;

&lt;p&gt;For PHP developers looking to add TOTP-based authentication to their projects, TOTP Authenticator provides a simple, lightweight, and secure solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🔐 Secure Secret Generation: Generates cryptographically secure secrets with configurable lengths.&lt;/p&gt;

&lt;p&gt;⏱ Time-based OTP Generation: Produces 6-digit one-time passwords compliant with RFC 6238.&lt;/p&gt;

&lt;p&gt;✅ Code Verification: Validates user input with support for slight time drift to accommodate clock differences.&lt;/p&gt;

&lt;p&gt;📱 QR Code Generation: Creates URLs compatible with Google Authenticator and similar 2FA apps.&lt;/p&gt;

&lt;p&gt;🔒 Timing-Safe Comparison: Protects against timing attacks during code verification.&lt;/p&gt;

&lt;p&gt;💡 Zero Dependencies: Pure PHP library (requires PHP 7.4 or higher).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;br&gt;
Install the library easily using Composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require hosseinhezami/totp-authenticator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Getting Started&lt;/strong&gt;&lt;br&gt;
Here's a quick example demonstrating the core functionality of the library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use HosseinHezami\TotpAuthenticator\Authenticator;

// Generate a secure secret
$secret = Authenticator::createSecret(16);

// Generate a TOTP code
$code = Authenticator::generateCode($secret);

// Verify the code
$isValid = Authenticator::verifyCode($secret, $code);
echo $isValid ? "Valid code" : "Invalid code";

// Generate a QR code URL for Google Authenticator
$qrCodeUrl = Authenticator::generateQrCodeUrl("user@example.com", $secret, "MyApp");
echo $qrCodeUrl;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The QR code URL can be scanned directly in any TOTP-compatible authenticator app.&lt;br&gt;
Verification uses timing-safe comparison to ensure maximum security.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Laravel Integration Example&lt;/strong&gt;&lt;br&gt;
Integrating this library into a Laravel project is straightforward. For example, a route can be defined to test all the functionalities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use HosseinHezami\TotpAuthenticator\Authenticator;
Route::get('/totp-test', function () {
    $secret = Authenticator::createSecret(16);
    $code = Authenticator::generateCode($secret);
    $isValid = Authenticator::verifyCode($code, $secret);
    $qrCodeUrl = Authenticator::generateQrCodeUrl('testuser@example.com', $secret, 'MyApp');

    return response()-&amp;gt;json([
        'secret' =&amp;gt; $secret,
        'generated_code' =&amp;gt; $code,
        'verify_code' =&amp;gt; $isValid,
        'qr_code_url' =&amp;gt; $qrCodeUrl
    ]);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This provides a ready-to-use JSON response for testing secret generation, code verification, and QR code creation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use TOTP Authenticator?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lightweight &amp;amp; Minimal Setup: Easy to integrate without heavy dependencies.&lt;/li&gt;
&lt;li&gt;Secure &amp;amp; Standards-Compliant: Follows RFC 6238 and implements cryptographically secure operations.&lt;/li&gt;
&lt;li&gt;Flexible: Works in both plain PHP and frameworks like Laravel.&lt;/li&gt;
&lt;li&gt;Developer-Friendly: Provides all the core TOTP functionality without complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/hosseinhezami/totp-authenticator" rel="noopener noreferrer"&gt;https://github.com/hosseinhezami/totp-authenticator&lt;/a&gt;&lt;br&gt;
Packagist: &lt;a href="https://packagist.org/packages/hosseinhezami/totp-authenticator" rel="noopener noreferrer"&gt;https://packagist.org/packages/hosseinhezami/totp-authenticator&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>totp</category>
      <category>authentication</category>
      <category>2fa</category>
    </item>
  </channel>
</rss>
