A Machine
The credentials that prove a machine is one signed in to its account: its machine key and the assertion it signs with it, the sealing key what's sent to it is sealed to, and the device code of its login.
The machine key
A key pair a machine makes when it signs in. The account service keeps only the public half, so nothing it holds, or loses, signs in as the machine.
- Proves: this machine is one signed in to its account.
- Made by:
lnk auth login, on the machine: an Ed25519 key pair from the system's random source. The login sends the public half; a person approves it in the browser (the device code), and the account service keeps it with the machine's id. No private half ever crosses a network. - Held by: the accounts plugin alone. In the Keychain on a Mac
(
machine-key, as Secrets in the Keychain keeps every item), else in~/.lnk/config.toml, mode 600. - Travels: never. It signs a machine assertion for each access token.
- Lasts: until the machine is signed out.
- Revoked: by
lnk auth logouton the machine,lnk iam machine remove <machine>from any other of the account's, or in the browser. The account service deletes the public half, and every signature after is refused. Access tokens already made last out their life. - May: get access tokens for its account, for any audience and scope a machine may have. Nothing else takes it or its signature.
A box's machine key
lnk box create signs in the box it made the same way, without a
browser: the box makes its own pair and sends back the public half, and
this machine adds it to the account with an access token (lnk auth key, lnk iam machine add, then lnk auth login --granted on the box).
The sealing key
What the account service seals a connection's token to, when you connect a connection to one of this machine's agents in the browser, so only this machine opens it as the browser delivers it over the remote relay. The account service keeps neither the token nor its sealed value.
- Proves: nothing: it only opens what was sealed to it.
- Made by: the remote plugin, the first time it takes actions
(
lnk remote start --actions,lnk remote watch --actions): an X25519 key pair from the system's random source, link-secret-value's own (Recipient), kept rather than made for one transfer, so a connection connect reaches the same recipient across reconnects. It is separate from the machine key, which only signs. - Held by: the remote plugin alone. In the Keychain on a Mac
(
remote/sealing-key), else in~/.lnk/remote/sealing-key, mode 600. - Travels: never. Its public half goes with every report that takes
actions (
seal_to), which this machine's access token carries, and the account service keeps it with the machine. - Lasts: until the plugin is uninstalled with its
sealing-keypart, or the file is removed: the plugin makes another, and a connect sealed to the old one fails, saying to ask again. - May: open what the account service sealed to this machine, for the agent and kind of action it was sealed for: HPKE (RFC 9180) in its base mode, X25519, HKDF-SHA256 and ChaCha20-Poly1305, as link-secret-value seals every value.
- Made once: under a lock beside it, so two first runs at once keep one key; a Keychain that can't be read (locked, or asking for a person) is an error, and a key is never made over one that's there.
Sealed for this machine alone
What's sealed names this machine's id at the account service with the
agent (<machine id>/<agent>), so a copy of its settings on another
machine, signed in as that one, opens nothing sealed for this one.
The machine assertion
What a machine sends the account service for an access token: a JWT signed with its machine key, good for one request.
| Part | Holds |
|---|---|
| Header | alg EdDSA, typ machine+jwt, and nothing else |
iss | The machine's id |
sub | The account's id, acct-<32 hex> |
aud | The account service's origin, https://accounts.example.com |
resource | The audience of the access token asked for |
scope | Its scope |
iat, exp | When it was made, and at most 60 seconds later |
jti | 16 random bytes, base64url |
The account service checks the signature with the machine's public
half, aud its own origin, exp at most 60 seconds after iat, and
the jti unseen while the assertion could be taken, so one sent twice
is refused. A machine's clock may be 2 minutes off either way: iat no
more than that ahead, exp no more than that behind, and the jti is
kept that much longer. A machine signed out has no public half there,
and is refused.
The device code
What a machine and a person share for one login, as OAuth's device flow does it.
- Proves: the machine collecting a login is the one that began it (the device code), and the person approving it is looking at that machine's login (the user code).
- Made by: the account service, when
lnk auth loginbegins. - Held by: the machine (the device code, which no browser sees),
and the person (the user code, 8 letters, which
lnk auth loginprints for them to check in the browser). - Travels: the device code from the machine to the account service only; the user code by the person's eyes.
- Lasts: 10 minutes, and is used once.
- Revoked: by Deny in the browser, or by expiring.
- May: add one machine to the account of the person who approved it.