<!-- https://docs.elchi.dev/passkeys | EAuth | Elchi Docs -->

# Passkeys

A way to sign in that a convincing copy of the sign-in page cannot capture.

## Why this is different from a password or a code

A password or a six-digit code can be typed into a fake page and replayed. A
passkey cannot: the browser binds it to the site it was created for and
refuses to use it anywhere else. The person does not have to notice the
phishing, because the credential does.

Every passkey made through EAuth belongs to `https://eauth.me`. That is the only
place it works, which is the point.

## What your application does

Nothing. Passkeys are on for every application, and signing in with one
happens on EAuth's own pages, so your integration receives the same
authorization code and the same tokens it gets after a password. There is no
setting and no SDK call.

## How a person uses one

**Adding one.** On their account page at `https://eauth.me/account`, under Security,
with the account's password to confirm. The page needs a sign-in first, and a
sign-in starts at your application, since the account belongs to it: link to
the account page from your application's settings, where the person is
signed in already. A passkey is a way in that survives a
password change, so a browser that happens to be signed in is not enough to
leave one behind. Every addition is mailed to the account's address, with
what to do if it was not them. They can add several, a phone and a hardware
key for instance, so losing one is not losing access.

**Signing in.** The sign-in page offers the passkey without the address being
typed first: as a suggestion in the address field where the browser supports
that, and with the button "Sign in with a passkey" everywhere else. The
browser shows the passkeys it holds for EAuth, the person picks theirs, and
the sign-in continues exactly as after a password.

**Removing one.** From the same page. A removed passkey stops working at once.

## Accounts and applications

An account at your application signs in to your application only, with a
passkey as with a password. Every application's passkeys belong to the same
site, so a person with accounts at two applications may be offered both; the
one for another application is refused with a message that says so, and
nothing is signed in.

## Two-factor accounts

A passkey whose authenticator checked the person, with a PIN, a fingerprint
or a face, is two factors on its own: something they have and something they
know or are. Such a sign-in is complete. A passkey that only registered a
touch is one factor, and an account that turned on two-factor is asked for
its code as after a password.

## What we store

| Value | Why |
|---|---|
| Credential ID | Identifies which passkey is being used |
| Public key | Verifies the signature |
| Sign count | Detects a copied authenticator |
| Transports | Lets the browser prompt for the right thing |
| Name | What the person called it, shown on their account page |

There is no private key here and never can be. It stays in the authenticator,
which is what makes a copy of our database useless against a passkey.

Every challenge works once, for five minutes. An unanswered one is deleted
within the hour.

## The counter check

An authenticator increments a counter on every use. A value that fails to
advance is the documented signal that the credential has been copied.

We do not merely refuse that sign-in: the passkey is removed. If it has been
copied, the copy works too, so leaving it registered would leave the account
open to whoever holds the copy. The person is told to sign in with their
password and add a new one.

Passkeys that sync through a platform keychain do not keep a counter and
always report zero. That is expected and is not treated as a copy.

## Losing a passkey

Nothing is lost with it: the account keeps its password. Sign in with that,
or reset it by email if it is forgotten, and remove the lost passkey from the
account page.
