Protocol overview
Triauth is a challenge-response protocol. A website builds a request, the user's device signs it, and the website verifies the signature against public keys published in DNS. This page describes the parts. The reference implementation, triauth-js, and its conformance test vectors define the exact behavior.
The parts
Identifiers
An identifier is username@domain, in lowercase. The domain part tells a verifier where to look. The username part, together with the domain's mode, tells it under which DNS name the identity's records are published.
DNS records
Two DNS names matter for each identifier. The domain itself carries the triauth record, which names the authenticator and sets the mode. A name derived from the identifier carries the identity records: keys, profile, groups, and delegations. See DNS records.
The challenge
A challenge is the request that a website makes. It names the website's callback URL, the request type, the identifier, a random value, the time, and the protocol version. For a sign-in, the decoded challenge looks like this:
json
{
"cburl": "https://example.com/cb",
"type": "auth",
"identifier": "john@triauthdemo.org",
"nonce": "ABEiM0RVZneImaq7zN3u_wAR",
"iat": 1777454675000,
"ver": 1
}The website encodes it as one string and sends the user's browser to the authenticator with it, in the address of the sign-in page:
https://auth.triauthdemo.org/auth.html#?challenge=eyJjYnVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vY2IiLCJ0eXBlIjoiYXV0aCIsImlkZW50aWZpZXIiOiJqb2huQHRyaWF1dGhkZW1vLm9yZyIsIm5vbmNlIjoiQUJFaU0wUlZabmVJbWFxN3pOM3Vfd0FSIiwiaWF0IjoxNzc3NDU0Njc1MDAwLCJ2ZXIiOjF9The response
A response is a signature envelope, a single text string. It records the request type, the identifier, an actor if someone signed on the identifier's behalf, the base URL of the website, the version, the time of signing, optional signed metadata, optional unsigned metadata, and one signature per key of the device. A verifier checks each signature against the keys published for that device.
|auth;john@example.com;;https://example.com/;v1;1787224766683;;;S8lEY3KOYs9gsSpCJ8YnbnKHVCJcT0dXRREZCAgfIR_3dqkW3S9eUcfQZc6q2HD2sy56LwndOoSbcGyO2ZbUnw|The parts are separated by ; and appear in this order.
| Part | Meaning |
|---|---|
| and | | Wrap the response. When several identities sign, as in an attestation, their parts are joined inside one pair of wrappers, separated by |. |
auth | The request type. A signature for one type is never valid for another. |
john@example.com | The identifier that the signature speaks for. |
(empty) | The actor. Empty when the identifier's own keys signed. For a delegated signature, the identifier of the actor. |
https://example.com/ | The base URL of the website's callback URL, its origin and path up to the last slash. The signature is valid only there. |
v1 | The protocol version. |
1787224766683 | The time of signing, in milliseconds since 1970, by the device's clock. |
(empty) | Signed metadata, encoded and covered by the signature. Holds extras such as extension data, attachment digests, and lookup codes. |
(empty) | Unsigned metadata, encoded and not covered by the signature. Carries only transport details of security-key signatures. |
S8lEY3KO…O2ZbUnw | The signature. A device with several keys puts one signature per key here, separated by ;. |
The five request types
Every request that a website makes has a type. The type is written in the challenge and in the response, and it decides what the authenticator shows the user, what the device signs, and how long the request stays valid.
| Type | What the user sees | What the website gets |
|---|---|---|
auth | A sign-in to approve or deny | Proof that the user controls the identifier |
ping | Nothing. Answered in the background with a token | Proof that the device still holds its keys |
sign | A message and files to review and sign | A transferable signature over the message |
stamp | Nothing. Answered in the background with a token | A signature over a short message, for third parties |
attest | Confirmations to complete with a provider | The provider's signature bundled with the user's |
All types share the three stages of the sign-in flow and the same response envelope structure.
Verification
A verifier reads the domain's triauth record, derives the name of the identity records, reads the keys, and checks the signatures. It also checks that the response matches the request, that it is fresh, that it was made for the verifier's own base URL, and that every applicable key of the signing device took part. Records that DNSSEC-validating resolvers confirmed mark the result as secure.