Skip to main content
Add a Sign in with AFAuth button and a human lands in the account their agent created. Your service acts as an OIDC relying party to the trust attestor’s OpenID Provider. This page is the how-to; the concept is the why.
No SDK helper yet. The trust attestor’s OIDC side is live, but the reference SDK doesn’t ship a drop-in RP handler — you hand-wire the callback (roughly the same shape as a “Sign in with Google” route). It’s a small amount of standard OIDC code; the snippets below are complete.

Prerequisites

  • A service_did you already use for attestation (§4.3) — sign-in reuses it, it is not a new identifier.
  • Agents that sign up attested (linked to their human), so accounts carry a sub_h. See Preconditions if some accounts were created as guests first.

1. Register as an OIDC client

Ask the attestor operator to register your service. A client binds three things (§10.8.3): For trust.afauth.org, the operator sets this in the TRUST_OIDC_CLIENTS environment variable:
Running your own attestor? The same registry lives in your attestor’s config — see Run your own attestor.

2. The flow

Standard OIDC Authorization Code + PKCE (S256). Discovery is at https://trust.afauth.org/.well-known/openid-configuration.

3. Start the sign-in (authorize)

Generate a PKCE verifier + challenge and a state/nonce, stash them in a short-lived store keyed by state, and redirect:

4. Handle the callback (token + verify)

Exchange the code at the token endpoint, then verify the id_token against the trust JWKS:
jwtVerify checks the signature, iss, aud, and exp for you; the explicit nonce check closes the loop opened at the authorize step.

5. Resolve to the account — canonicalize the issuer

The account lives under (iss, sub_h), where sub_h is id_token.sub. The catch: your attestation path stored iss = "afauth-trust", but the id_token carries the URL. Map both to one issuer before you look up, or the human lands in a new empty account:
This canonicalization is the one thing that silently breaks sign-in. The agent’s attestation iss is the bare string afauth-trust; the id_token iss is https://trust.afauth.org. They are the same attestor — treat them as one before keying the account (§10.8.4). Store your attestation issuer canonicalized too, so both paths agree.

Preconditions

Sign-in resolves an account by (iss, sub_h), so the account needs a sub_h. That is written when an agent signs up attested (after linking to its human). Two cases to know:
  • Attested signup, then sign-in — works immediately; the signup wrote sub_h.
  • Guest signup, then link, then sign-in — the guest account had no sub_h. Because signup is idempotent on the agent’s did:key, the principal binds on the agent’s next attested request after linking. After that one request, sign-in resolves to the same account. (Until then, the human signing in would resolve to nothing and see “no account yet”.)

What sign-in does not do

Signing in authenticates the human to the (iss, sub_h) account — it does not transfer ownership. It does not run the claim ceremony or raise the §7.5 owner-binding floor. If you want a recoverable human owner (recovery contacts, credential enrollment), run a claim alongside sign-in — they compose. See §10.8.5.

Where to next

Sign in with AFAuth (concept)

The (iss, sub_h) = OIDC (issuer, subject) idea, in full.

Accept trust attestations

The agent-side gate that writes sub_h in the first place.

Invite and claim

Establish a recoverable human owner alongside sign-in.

Trust API reference

Full OIDC endpoint and id_token shapes.