Authentication
atreoAGENT uses a multi-layered authentication model. The agent authenticates with atreoLINK, mobile clients authenticate with the agent, and proxied requests are authorised against the per-member ACL.
Device authentication (agent → atreoLINK)
Section titled “Device authentication (agent → atreoLINK)”The agent authenticates to atreoLINK using a bearer token issued at pair time, stored in config.yaml as device_token. The token is sent on REST calls and as a query-string parameter on the WebSocket upgrade.
This token only authenticates the agent’s transport with atreoLINK. It does not authorise any state mutation: every state-changing message that arrives over the control channel is independently verified against the pinned owner identity (see Pairing and Encryption).
Owner identity pinning (agent’s source of truth)
Section titled “Owner identity pinning (agent’s source of truth)”When you pair the device, the agent permanently pins your account’s identity in admin_pin.json. From then on:
- Any management message claiming to come from the owner must be signed by that pinned identity.
- atreoLINK cannot substitute or rotate the owner identity by itself. The agent rejects any
member:added/app:upserted/ etc. that tries to mutate the pinned admin entry. - Every state-changing message carries an envelope signature with
intentandtsfields. The agent verifies the signature, checks the intent binds to the expected command and target, and enforces a 120-second replay window on fresh commands. See Tunnel Protocol for the full model. - This is the keystone of the trust model: atreoLINK brokers the connection but is not trusted to authorise changes. It could be malicious or compromised, and the agent would still only execute commands signed by you.
User identity keys
Section titled “User identity keys”Each user (owner and member) has a long-term identity keypair, generated client-side at registration. The private key is wrapped with a password-derived key (see Encryption for the details) and uploaded to atreoLINK as an opaque blob. atreoLINK only ever sees the public key in plaintext.
| Where the private key lives | Storage |
|---|---|
| iOS / iPadOS / tvOS | iOS Keychain |
| Android / Android TV | Android Keystore |
| Browser | IndexedDB (per-origin) |
The same identity keypair is used for both signing state-changing envelopes and receiving encrypted notifications. See Encryption for the cryptographic detail.
Member authentication (mobile → agent)
Section titled “Member authentication (mobile → agent)”Mobile clients are authenticated through a challenge-response protocol over the atreoLINK control channel:
- Mobile sends
wg:challengeto the agent as a member-signed envelope (intent + ts, signed under the member’s identity key). - Agent verifies the envelope against the member’s pinned
identityKeyfrom the ACL, then returns a random nonce (5-minute validity). - Mobile sends
wg:provisionas a member-signed envelope binding (memberId, clientId, nonce, ts) plus its WireGuard public key. - Agent verifies the envelope against the member’s pinned
identityKey(not against any pubkey in the request body) and confirms the nonce matches the one it issued. - On success, a WireGuard peer is added and a tunnel IP is allocated.
- Agent signs the provisioning response (covering server pubkey, tunnel IP, endpoint, allowed IPs, and keepalive) with its long-term identity key. Mobile verifies this against the agent’s identity pubkey it pinned at pair time. See Encryption for the transcript shape.
After provisioning, every subsequent packet is authenticated by WireGuard. Only peers with registered public keys can send traffic through the tunnel.
Request authentication (proxy layer)
Section titled “Request authentication (proxy layer)”For HTTPS requests through the reverse proxy:
- The proxy extracts the source IP.
- If the IP is in a trusted network, access is granted as
adminimmediately. - Otherwise, the IP is looked up in the ACL by tunnel IP.
- The member’s
allowedAppslist is checked against the requested hostname’s slug. - Access is granted (200 plus
X-Auth-User/X-Auth-Member-ID/X-Auth-Roleheaders) or denied (403).
There are no passwords or session cookies in the request-authentication path. Identity is determined entirely by the WireGuard tunnel IP, which is bound to the member’s identity key from step 4 above.
Key hierarchy
Section titled “Key hierarchy”The full set of keys (device identity, owner identity, member identity, WireGuard, push transport, notification content, ACME) is documented in Encryption.
© 2026 atreoLABS. All rights reserved.
WireGuard is a registered trademark of Jason A. Donenfeld.

