Milind Daraniya

Passkeys: A Better Way to Add Passwordless Login to Web Applications

Published September 27th, 2026 11 min read

I have started seeing passkeys in more modern applications.

Most websites still use:

Email + Password

Some also add:

Password + OTP

But passkeys provide another way:

Passkey
   ↓
Fingerprint / Face / PIN
   ↓
Login

The user does not have to type a password.

This is becoming more important for developers because WebAuthn Level 3 became a W3C Recommendation on August 25, 2026. WebAuthn is the web standard used to implement passkey authentication.

What is a passkey?

A passkey is based on public-key cryptography.

When the user creates a passkey, the device or credential manager creates a key pair:

Private Key
Public Key

The private key stays with the authenticator on the user's device.

The website stores the public key.

So the server does not need to store the user's passkey secret like it stores a normal password hash.

The basic flow is:

User
 ↓
Browser
 ↓
Authenticator
 ↓
Private Key signs challenge
 ↓
Server verifies with Public Key
 ↓
Login successful

How does login actually work?

First, the server creates a random challenge.

Then JavaScript uses:

navigator.credentials.get()

The browser asks the user's authenticator to prove that the user has the correct passkey.

The authenticator signs the challenge with the private key.

The browser sends the result back to the server.

The server verifies the signature using the stored public key.

If everything matches, the user is logged in.

So the important thing is:

The server verifies proof of the private key without receiving the private key itself.

Registration flow

When a user enables a passkey, the flow is roughly:

User clicks "Create Passkey"
        ↓
Server sends registration options
        ↓
Browser
        ↓
Authenticator creates key pair
        ↓
Public key returned to application
        ↓
Server stores credential

The private key remains with the authenticator.

The stored information on the server is mainly the credential ID and public-key-related data needed for future verification.

Login flow

Later, the user clicks:

Sign in with Passkey

Then:

Server
 ↓
Creates challenge
 ↓
Browser
 ↓
Passkey
 ↓
Signs challenge
 ↓
Browser sends assertion
 ↓
Server verifies
 ↓
User logged in

The browser API used for this is:

navigator.credentials.get()

Passkey registration uses:

navigator.credentials.create()

These are part of the Web Authentication API.

Why is this different from a password?

With a normal password:

User
 ↓
Password
 ↓
Server

The user knows the secret and types it into the website.

With passkeys:

User
 ↓
Device Authenticator
 ↓
Private Key
 ↓
Signature
 ↓
Server

The private key is not typed into the website.

This also reduces the number of password-related problems that developers need to handle.

What can the user use as a passkey?

A passkey does not necessarily mean a fingerprint only.

Depending on the device, it can use:

Fingerprint
Face recognition
Device PIN
Windows Hello
Phone authentication
Password manager
Security key

The actual authenticator can be built into the operating system, browser environment or provided by hardware.

So from the developer side, I don't need to implement fingerprint scanning myself.

The browser and operating system handle that part.

What does JavaScript need to do?

The frontend mainly talks to the browser's WebAuthn API.

For registration:

const credential =
    await navigator.credentials.create({
        publicKey: options
    });

For authentication:

const credential =
    await navigator.credentials.get({
        publicKey: options
    });

The important part is that the frontend does not independently verify the passkey.

The backend must validate the result.

That means the architecture is still:

React / JavaScript
       ↓
Laravel / PHP API
       ↓
WebAuthn verification
       ↓
User session

What should I store in the database?

I would not treat a passkey like a normal password field.

A separate table is normally more practical.

For example:

user_passkeys

id
user_id
credential_id
public_key
counter
device_name
created_at
last_used_at

The exact fields depend on the WebAuthn library and implementation.

The important idea is that one user can have multiple passkeys.

For example:

Milind
 ├── Laptop
 ├── Android Phone
 └── Security Key

This is important because users may sign in from multiple devices.

Do I need to remove passwords?

No.

I would initially support both:

Password Login
       +
Passkey Login

Then users can create a passkey from account settings.

For example:

Account Settings
    ↓
Security
    ↓
Passkeys
    ↓
+ Add Passkey

This gives users a gradual migration path.

Passkeys are also useful for 2FA

Passkeys are not only useful as the primary login method.

WebAuthn can also be used as an additional authentication factor. MDN documents both passwordless authentication and secure multi-factor authentication through WebAuthn.

For example:

Email + Password
        +
Passkey

can provide an additional security layer.

HTTPS is required

One important implementation detail is that WebAuthn requires a secure context, which normally means HTTPS for a real website.

So for production:

https://example.com

is expected.

For local development, developers can use the browser's supported secure local-development setup.

What about my Laravel API?

For a Laravel application, I would keep the responsibilities separate.

Something like:

React
 ↓
Laravel API
 ↓
Passkey Service
 ↓
WebAuthn Library
 ↓
Database

The React application handles the browser interaction.

Laravel handles:

  • User identification
  • Challenges
  • Credential storage
  • WebAuthn verification
  • Session/token creation
  • Removing passkeys
  • Managing multiple devices

This fits well with API-based applications.

What about mobile apps?

The same idea is also useful for mobile applications.

A SaaS application can have:

Web
 ↓
Passkey

Mobile
 ↓
Passkey

Backend
 ↓
Same user account

The exact implementation is platform-specific, but the authentication concept stays based on public-key credentials.

This is useful when the same account is used across web and mobile.

One important thing: recovery

Passkeys make login easier, but developers still need to think about account recovery.

What happens when:

Phone is lost
Laptop is replaced
Passkey is deleted
User cannot access the old device

So I would still provide a secure recovery process.

For example:

Existing Passkey
       OR
Recovery Method
       OR
Verified Account Recovery

The recovery process should not simply become a weak backdoor.

Why I think developers should watch this

The adoption numbers are also interesting.

The FIDO Alliance reported in May 2026 that an estimated 5 billion passkeys were in active use worldwide. Its 2026 research also found that 75% of surveyed consumers had enabled a passkey on at least one account, based on research across 11 countries including India.

So this is no longer just an experimental browser feature.

There is already significant real-world usage.

My practical approach

For a new SaaS application, I would design authentication like this:

Login
 ├── Email + Password
 ├── Passkey
 └── Account Recovery

After login:

Settings
   ↓
Security
   ↓
Passkeys
   ↓
Add / Rename / Remove

And I would allow multiple passkeys per user.

My takeaway

For me, the interesting part of passkeys is not simply that users don't have to type passwords.

The bigger change is the authentication model.

Instead of:

Store Password
      ↓
Check Password

we have:

Create Public/Private Key Pair
          ↓
Store Public Key
          ↓
Challenge User
          ↓
Verify Signature

WebAuthn is now a mature web standard, and Level 3 became a W3C Recommendation in August 2026.

I would not remove passwords from an existing application immediately.

But for a new project, especially a SaaS application with web and mobile clients, I think passkey support is worth designing into the authentication system from the beginning.