| Internet-Draft | Acts-For | October 2026 |
| Morrison | Expires 24 April 2027 | [Page] |
Acts-For lets a person sign in to any website with the ~handle they already hold, and lets an AI agent sign in or register at that website on the person's behalf. Neither needs a username, a password or an account per site. A website joins by publishing one DNS record. A person signs in through a standard OpenID Connect authorization code flow and the site receives a short-lived token naming the person by a number unique to that site. An agent obtains a short-lived pass from the issuer over the Model Context Protocol and presents it to the site. The pass names the same per-site number, the agent's own key and ~handle, and the limits the person set. The site checks it against a published key and calls nobody.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 24 April 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document.¶
Most websites ask a person to register with a username, a password and an email address to confirm. Single sign-on from a large provider removes the password but ties the person to that provider and gives every site the same identifier for them. An agent that has to place an order or book a table for a person either holds the person's password, which it should never be given, or stops and hands the task back.¶
Under Acts-For the person signs in with a ~handle they already hold ([MCPDNS], Section 2). A website that wants to accept it publishes one DNS record. That record proves the site controls its domain and registers the site as a client in the same step. From then on:¶
a person clicks "Sign in with ~alter" and confirms with a passkey. The site learns a number that identifies the person to that site only. It learns the person's ~handle or email only if the person shares them;¶
an agent the person has authorised asks for a pass for that site over MCP and presents it. The pass names the person by the same per-site number and the agent by its own key. The site then knows who the person is to it and which agent is acting.¶
Out of scope are how a person obtains a ~handle, how the person grants authority to an agent (only the grant's effect on the pass is specified here), payment, and anything the site does after sign-in.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
An identifier as defined in [MCPDNS], Section 2, with the grammar of
handle-name in [ALTERURI], Section 3.3, and the tiers of
[IDCOMMITS], Section 3. The tier is read from the lexical form alone:
a trailing .bot is the Bot tier, a leading cc- is the Instrument
tier, and anything else is the Sovereign tier. Where this document
names a ~handle as a reference it is written as an alter: URI
[ALTERURI], as [MCPDNS] does.¶
A human who holds a Sovereign-tier ~handle.¶
Software acting for a Person under scoped delegation, holding its own signing key and its own Bot-tier ~handle ([IDCOMMITS], Section 3). An Instrument-tier ~handle is never an Agent under this document, because it has no envelope of its own and is not an independent principal ([ALTERURI], Section 3.4).¶
A website that accepts sign-in under this document. Its operator is the Site owner.¶
The Sovereign-tier ~handle a Site receives when its record verifies (Section 4.4).¶
The service that authenticates the Person, issues tokens and passes, and publishes the keys that verify them. In the deployment described in Section 8 this is ~alter.¶
The identifier the Issuer gives a Person for one Site (Section 5.3).¶
The token an Agent presents to a Site (Section 6.2).¶
The Issuer's Ed25519 key that signs acts-for passes, published at the
Issuer's /.well-known/alter-keys.json (Section 6.2).¶
A Site handle held by more than one Person (Section 4.4).¶
Site owner DNS Issuer Person / Agent
| | | |
| 1. publish _alter record | |
|--------------->| | |
| 2. verify | | |
|---------------------------------->| |
| | 3. read record | |
| |<-----------------| |
| 4. Site registered as a client | |
|<----------------------------------| |
| | |
| Person: 5. click, passkey, consent (OIDC + PKCE) |
|<------------------------------------------------------->|
| 6. ID token, sub = per-site subject |
| |
| Agent: 7. ask for an acts-for pass over MCP |
| |<--------------------|
| 8. present pass, signed by the Agent's key |
|<--------------------------------------------------------|
| 9. verify pass against the Issuer's published key |
Steps 1 to 4 happen once per Site. Steps 5 and 6 are the person signing in. Steps 7 to 9 are an agent signing in for the person.¶
A Site joins by publishing one TXT record at the label _alter
prepended to its domain [RFC8552], as the envelope record of [MCPDNS]:¶
_alter.riverbakery.example. IN TXT "v=alter1; h=~riverbakery.example; pk=ed25519:<key>; ilr=<digest>; ts=<unix-seconds>; rev=<digest>; sig=<signature>; code=<code>"¶
The fields v, h, pk, ilr, ts, rev and sig are the
envelope of [MCPDNS], Section 7, signed over the input of [MCPDNS],
Section 7.4, with these values:¶
h is the Site handle (Section 4.2), with its leading tilde as
[MCPDNS], Section 7.3.2 requires;¶
pk is an Ed25519 public key [RFC8032] generated on the Site owner's
device. The private key MUST NOT leave that device;¶
ilr is, as built, the base64url [RFC4648] SHA-256 of the JSON
canonical form [RFC8785] of the object with members h, domain
and ts;¶
rev is the SHA-256 of a revocation pre-image held by the Site
owner.¶
The record also carries one field [MCPDNS] does not define, code, a
one-time code the Issuer hands the Site owner when the claim starts.
code sits outside the signed input. The same signed envelope can be
published again with a new code and no new signature. A resolver
that implements [MCPDNS] alone ignores it ([MCPDNS], Section 7.5).¶
ilr and code do not conform to [MCPDNS]. Its Section 7.3.4 defines
ilr as the digest of an IdentityLog root, and its Section 7.5 forbids
repurposing a required field and admits a new field only with a new
envelope version. Here ilr is a binding digest and code is a new
field under v=alter1. See Section 13, item 3.¶
The Site handle is ~ followed by the Site's domain, in lowercase, in
its A-label form [RFC5890], with no trailing dot. The domain the record
proves is its zone, and the Site handle's dispatchable reference
carries that zone as its org-scope:¶
alter:~riverbakery.example@riverbakery.example¶
The spelling of a Site handle never establishes its zone. A party
that reads ~riverbakery.example MUST NOT resolve it against the
riverbakery.example zone on the strength of its characters
([ALTERURI], Section 6.9; [MCPDNS], Section 12.3). Only the verified
record, or a reference that carries the zone, does.¶
A domain whose Site handle would not be a Sovereign-tier
handle-name MUST NOT be enrolled. That excludes:¶
a domain whose first label begins with a digit, since handle-name
does not admit it;¶
a domain whose first label begins with cc-, since its Site handle
reads as an Instrument-tier handle;¶
a domain under the bot top-level domain, since its Site handle
reads as a Bot-tier handle.¶
See Section 13, item 11.¶
The Issuer verifies a Site record when the Site owner asks it to, and MUST check all of the following:¶
the record parses as an envelope with every required field;¶
sig verifies under pk over the envelope's canonical signing
input;¶
h equals the ~handle being claimed;¶
ts is within seven days of the start of the claim, with five
minutes allowed for clock skew;¶
ilr equals the value computed from h, the domain and ts;¶
the digest of code equals the digest the Issuer stored when the
claim started. The Issuer stores only the digest.¶
The first record to verify wins and clears every other pending claim on that domain. DNSSEC validation is reported but not required. This conflicts with [MCPDNS], Section 8. That section requires a signed zone for every record at this label, and requires an onboarding wizard or recognition verifier to treat a record read over an unvalidated path as unauthenticated TXT. A Site handle from an unsigned zone also fails step 2 of [MCPDNS], Section 12.3 and step 3 of [ALTERURI], Section 3.4. The Issuer accepted it and no third party can verify it. See Section 13, item 1.¶
A Site record already published under the same pk MAY be accepted in
place of a new one, without a new code, when the claimant proves
possession of the matching private key. This lets a Site owner who has
set up once, on the same device, add a second domain or return without
editing DNS again.¶
A verified Site record produces, in one step:¶
the Site handle (Section 4.2), owned by the Site owner's own ~handle as a sole-owned entity. An owner who does not already hold a ~handle claims one in the same flow, and the Site is paired to a person from the start. When a second person joins, the Site handle becomes a collective and is held under the collective's own rules. Members of a collective need not all hold the same permissions. Only the owner can change the Site's client;¶
an OAuth 2.0 client [RFC6749] for the Site. The client is public
(token_endpoint_auth_method is none), its scopes are openid and
profile, and its single redirect URI is one exact https address
on the proven domain or its www. name, with no wildcard, port,
user information or fragment.¶
The Site needs no separate client registration [RFC7591].¶
A Person who signs in to a Site, or for whom an Agent signs in, is the Site's counterparty. Sign-in never makes a Person a member of the Site handle.¶
The Site embeds a button and a script:¶
<div data-alter-sign-in></div>
<script src="https://issuer.example/sign-in/v1.js"
integrity="sha384-<hash>" crossorigin="anonymous"
data-client-id="<client_id>"
data-return-page="https://riverbakery.example/callback"
data-issuer="https://issuer.example"
data-authorize="https://issuer.example/authorize"></script>
¶
The script is pinned by its integrity hash. A changed script is published at a new path.¶
The flow is the OpenID Connect authorization code flow [OIDC] with
PKCE [RFC7636], method S256, a one-time state and a nonce. The
Person confirms with a passkey at the Issuer, and the Issuer MUST
require user verification [WEBAUTHN]. That one gesture is two factors,
the device held and the fingerprint, face or PIN that unlocks it. The
Issuer MUST ask for it on every sign-in to a Site, including when the
Person already has a session at the Issuer. At the consent step the
Person MAY switch on sharing their ~handle, their email, or both. These
travel as the scopes handle and email, and only the consent step can
add them. email is the scope of [OIDC], Section 5.4. Neither scope
carries an alter: prefix, because a scope token with one would read
as an alter: URI [ALTERURI], and a scope is not one.¶
The Site receives:¶
an ID token, signed RS256 [RFC7518] by the Issuer, with iss the Issuer,
aud the client identifier, a lifetime of one hour, sub the
per-site subject (Section 5.3), verified set to yes, the same
band the acts-for pass carries (Section 6.2), and handle and email
only where the Person switched them on. email and email_verified
are the claims of [OIDC], Section 5.1. handle carries the Person's
~handle in the bare form of [MCPDNS], Section 7.3.2. auth_time is
the time of the passkey confirmation for this sign-in, never the time
the token was minted, and amr [RFC8176] lists the methods that
confirmation used;¶
an opaque access token, valid for 600 seconds, accepted only at the userinfo endpoint. No refresh token is issued.¶
The Site MUST verify the ID token's signature against the Issuer's
published JSON Web Key Set [RFC7517] before acting on it. Checking iss, aud,
exp and nonce in the browser is not enough.¶
The per-site subject is a pairwise identifier in the sense of [OIDC], Section 8.1. It is the lowercase base32 [RFC4648] encoding of the first 20 bytes of an HMAC-SHA256 [RFC2104], keyed by an Issuer secret, over a fixed label, the Person's internal identifier and the Site's domain, each prefixed by its length as a four-byte big-endian integer.¶
The domain is normalised once before use, and the same normalised
form is the pass's aud. It is lowercased, one trailing dot is
removed, it is taken in its A-label form [RFC5890], and then one
leading www. is removed. The fold is applied exactly once, because it
is not idempotent: www.www.example names the Site www.example.¶
The per-site subject never begins with ~ and can never be read as a
~handle.¶
A Person has the same subject at a Site whether they sign in themselves or an Agent signs in for them. At different Sites they have different subjects, and two Sites cannot join their records by subject.¶
An Agent that holds a grant from its Person calls the MCP [MCP] tool
alter_sign_in at the Issuer, naming the Site's domain. The Issuer
checks that the grant exists, is in force and covers that Site, then
returns an acts-for pass. The Issuer MUST refuse an Agent whose ~handle
is not Bot-tier.¶
alter_sign_in is a tool surface name in the sense of [TOOLNAMES];
see Section 11.¶
The pass is a CBOR Web Token [RFC8392] in a COSE_Sign1 structure
[RFC9052], algorithm EdDSA [RFC8032], signed by the Issuer's floor
key. It carries the registered claims iss (1), sub (2), aud (3),
exp (4), iat (6) and cti (7), and nbf (5) where present, and
the following claims under Private Use keys, below -65536 as
[RFC8392], Section 9.1 allows:¶
profile (-65537):the text alter-site-pass-v0. A verifier MUST refuse a pass whose
profile it does not know.¶
grant (-65538):the 32-byte content address of the grant the pass was issued under.¶
bands (-65539):a map of band name to text label. A site pass carries
{"verified": "yes"}. No number is ever a band value.¶
acting (-65540):a map naming the Agent: kid (its key), handle (its Bot-tier
~handle, in the bare form of [MCPDNS], Section 7.3.2), may_tools
(an array of tool surface names), valid_until (Unix seconds), and
optionally max_value (a map of amount, a decimal string, and
currency, a code).¶
cnf_jkt (-65541):The claims have these values:¶
iss is the text alter;¶
sub is the per-site subject of the Person at this Site, and is
never a ~handle;¶
aud is the Site's domain, normalised as in Section 5.3;¶
exp is at most 300 seconds after iat, never later than
acting.valid_until, and never more than 3600 seconds after iat.¶
acting and cnf_jkt MUST appear together. A pass presented without
both MUST be refused. The pass MUST NOT carry the Person's ~handle or
email; those reach a Site only through the ID token of Section 5.¶
Private Use keys are not interoperable between issuers. Whether these
claims should be registered, and whether cnf_jkt should instead be
the cnf claim of [RFC8747] carrying a COSE Key thumbprint
[RFC9679], is Section 13, item 2.¶
The Agent presents the pass to the Site with a request signed by its own key. This document does not yet say how the pass travels or how the request is signed (see Section 13, item 12). The Site MUST:¶
verify the pass under the Issuer's Ed25519 floor key, published at
the Issuer's /.well-known/alter-keys.json [RFC8615];¶
check profile, check that aud is its own domain normalised as
in Section 5.3, and check that exp has not passed;¶
verify the request signature under the Agent key whose thumbprint
is cnf_jkt, and check that the key's identifier equals
acting.kid. A pass presented without that signature MUST be
refused, since the pass alone is a bearer token;¶
hold the Agent to may_tools and max_value.¶
The Site then treats sub as it would after a Person sign-in. A
subject it has seen before is a returning Person. A new one is a
Person the Agent has just registered.¶
No token exchange [RFC8693] happens at sign-in. The Site does not call the Issuer.¶
A Site owner who loses the device holding the Site key proves the domain again by publishing a new record. Proving a domain again signs its owner straight back in only where the business account has no confirmed email; otherwise the way back is a link sent to that email. Proving a domain never signs anyone in to an account holding a personal ~handle, because proving a domain proves the business and not the person.¶
A Site handle whose owner leaves without handing it over becomes dormant. Proving its domain again revives it only after a wait in which the former owner, or any member, can object. Revival is never immediate, because control of a domain's DNS does not show who ran the Site.¶
Note to the RFC Editor: please remove this section before publication, per [RFC7942].¶
~alter has implemented most of this document in a test deployment. As of 19 October 2026:¶
Domain control is the only thing the Site record proves. Whoever controls a domain's DNS can enrol it, including a former agency, a new registrant of a lapsed domain, or an attacker holding the DNS host login. A published record counts for as long as it stays published, with no time limit, while the device that made it still holds its key. A seller who never finished setup and still holds that key can therefore claim a domain whose buyer leaves the old record in place. This is accepted. A record left up is still being published by whoever controls the zone, and any age bound would refuse every older record. A domain that was deleted and registered again is a different case. [MCPDNS], Section 13.1.2 already gives the signal for it, a changed registry creation date. See Section 13, item 5.¶
The Site handle spelled like a domain is a Handle-Domain Confusion surface ([ALTERURI], Section 6.9). A surface that shows a Site handle to a person MUST keep its leading tilde.¶
A session at the Issuer is never enough to sign a Person in to a
Site. A browser left signed in at the Issuer, on a shared or stolen
machine, would otherwise let whoever holds it sign in as the Person at
every Site. Each sign-in therefore asks for a fresh user-verified
passkey (Section 5), and auth_time reports when that happened. A
Site that sends max_age or prompt=login [OIDC] is always met,
because every sign-in is already fresh. A Site can read amr to see
how the Person confirmed.¶
A Site should act only on the ID token and only after checking its signature. The browser script does not check the signature and is not a substitute.¶
The acts-for pass is short-lived and bound to one audience. It is useless without a request signed by the Agent key it names. A Site that skips the signature check turns the pass into a bearer token valid for up to five minutes.¶
The one-time code is stored only as a digest. A claimant can satisfy only their own pending code and cannot replace another claimant's.¶
The per-site subject stops Sites joining their records by identifier. The Person's ~handle and email reach a Site only when the Person switches them on, and never through an acts-for pass. The Issuer sees every sign-in it issues for, and this protocol gives a Person no way to keep a sign-in from it.¶
The per-site subject does not stop Sites joining their records by the
Agent. acting.kid, acting.handle and cnf_jkt are the same at
every Site the same Agent signs in to. Two Sites that compare them
learn that their two per-site subjects are one Person. See Section 13,
item 10.¶
The Issuer holds the key the per-site subject is computed from and can compute any Person's subject at any Site.¶
This revision makes no IANA request. The _alter label is requested
in [MCPDNS]. A revision meant for publication would need to request:¶
For review before -01:¶
[MCPDNS] requires DNSSEC at _alter, and this document reports it
without requiring it, because most domains are not signed, large
ones included. A Site handle from an unsigned zone is then one that only
the Issuer accepts (Section 4.3). Either this document defines its
own label, or [MCPDNS] relaxes the requirement for business
records, or Sites must sign their zones. The _org-alter record of
[MCPDNS], Section 6 requires the organisation's registered legal
name and, per [MCPDNS], Section 8, only recommends DNSSEC.¶
Should the acts-for pass carry the Agent in an RFC 8693 act claim
and the key in the cnf claim of [RFC8747], where existing
verifiers can read them, in place of acting and cnf_jkt? The
other choice is to register the claims of Section 6.2.¶
Should the one-time code move to a separate, removable challenge
label and leave _alter holding only the long-lived envelope? That
would also let ilr return to the meaning [MCPDNS], Section 7.3.4
gives it, and both changes are needed for the record to conform to
[MCPDNS], Section 7.5.¶
Should a Site be able to enrol by publishing a file at its own
https origin instead of a DNS record, for owners who cannot edit
DNS?¶
Should the Issuer apply the change-of-control signals of [MCPDNS], Section 13.1.2 to a Site record? A domain deleted and registered again could then not be claimed under a record its former owner left up. That checks the registry's creation date and sets no age bound.¶
Can a seller with no domain of its own accept sign-in?¶
A Site publishing its own client metadata document, beside the one exact return page.¶
An agency setting up many client domains from one account, and handing each over.¶
The ID token is RS256 under a key in the Issuer's JSON Web Key Set
and the pass is EdDSA under the separate floor key, and the ID token's iss is the
Issuer's URL while the pass's is the text alter. Should the two
converge?¶
The same Agent signs in to every Site under the same key and ~handle. That joins the Person's per-site subjects (Section 10). Should an Agent present a key and ~handle per Site?¶
Which domains can become a Site handle. Section 4.2 refuses those
beginning with a digit, since handle-name does not admit them, and
those beginning with cc- or under bot, since they read as
another tier. Digit-led domains are common and [ALTERURI] may need
to admit them. A proven www. name is folded by the per-site subject and not
by the Site handle.¶
How the pass travels to the Site and how the Agent signs the request. HTTP Message Signatures [RFC9421], as Web Bot Auth [WBA] uses, is one candidate.¶
The grant is out of scope here. Should it be a consent grant of
[CONSENT], Section 5.2, with grant as the grant_ref of its
Section 5.3?¶
One-tap record writing at the DNS host (Domain Connect [DOMAINCONNECT]), where the Site owner never sees the record.¶
Who in a collective can act for its Site handle, change its client, or sign in to other Sites as it. Members need not all hold the same permissions. This revision does not cover an Agent acting for a collective.¶
draft-morrison-acts-for-00 (2026-10-19): first version.¶
None yet.¶