← UKK

UKK on kirjoitettu englanniksi ja hollanniksi; se näytetään englanniksi.

UKK

PC login protocol and offline policy

FAQ › Profile server › PC login · Nederlands

What is it?

How an EUZOS PC gets a signed profile and a pc token from the profile server. There are three online ways to log in, all ending in the same signed profile:

  1. QR code: the PC shows a QR code; the user confirms on the phone with Face ID / fingerprint (methode telefoon, or web via the fallback web page);
  2. e-mail address and password on the PC itself (methode=wachtwoord);
  3. Microsoft work account (Entra ID, device code flow; methode=microsoft).

After a password login the profile can also carry an offline token, so the PC can later log in offline for a limited number of days; when online again it reconnects (methode offline). With the pc token the PC then fetches its files list, polls its status (remote logout), writes back settings and uses the vault. The protocol between PC and server is plain text (text/plain, lines key=value), not JSON.

How do I…?

How does the QR login work, step by step?

  1. The PC creates a session id S (32 hex, in the QR code) and a pc secret G (32 hex, only in RAM).
  2. It polls GET /api/session/S?pc=G[&voorkeur=zakelijk|prive] every 2 s; the first poll creates the session, bound to the PC's IP and SHA-256(G). The answer is wacht + code=<pairing code>.
  3. The QR code is https://<domain>/l/<S>; the phone app (or the web page) fetches it; the poll then also says gezien=1 and the PC shows "Confirm on your phone…".
  4. The phone confirms (Phone app); the next poll gets ok + the signed profile, once.

Why does the QR code change every 30 seconds?

So a photo of the login screen is worthless after 30 s. As long as no phone fetched the code, the PC creates a new session every 30 s and revokes the old one with &intrekken=1; the server also lets an unfetched session lapse after qr_duration (30 s). Once fetched, the session stays valid for confirm_duration (120 s).

How does password login on the PC work?

POST /api/pc/login with email=, wachtwoord=, sessie=, pc=, pc-id= (+ voorkeur=). The password never goes into a URL. Answer: ok + the signed profile with methode=wachtwoord. Only confirmed (actief) accounts. It is throttled per account, per PC, per network and per IPv6 /48, with growing delays and a temporary lockout (429 with wacht=<seconds>). Switch it off with pc_password = no (then 404).

How does "Log in with Microsoft" work?

The PC runs the device code flow with Microsoft and sends only the ID token: POST /api/pc/entra (id_token=, sessie=, pc=, pc-id=, taal= [, nonce=]). The server checks the token against Microsoft's keys and the organisation's tenant and domains, links or creates the account, and answers like a password login with methode=microsoft and always soort=zakelijk. Details in Organisations.

How is a PC logged out remotely?

The PC polls GET /api/status?token=<pc-token> (about every 30 s). After a remote logout (app: pc-sessions/<ref>/logout), a block, a new password or Entra offboarding, the answer is afgemeld and the PC returns to the login screen. If the PC gets no valid answer for 15 minutes it logs itself out; it also logs out after 12 hours logged in (monotonic clock).

How do I log out from the PC?

The PC calls GET /api/logout?token=<pc-token> (always ok), after first sending pending settings.

How are my settings kept between PCs?

The PC writes changes back with POST /api/profile/settings?token=<pc-token> (only the changed keys, from a whitelist). The next signed profile contains them. Per user and per profile kind (Work or school / Private).

How does offline login get allowed, and for how long?

The server's offline policy: offline-policy '*' <days> for this environment or offline-policy @domain <days> for an organisation (domain of the e-mail address; the domain wins). 0 = not allowed; without a rule 14 days; at most 30. Only a password login hands out an offline token. See docs/OFFLINE-LOGIN.md for the PC's locker.

How do I take offline access away?

offline-revoke <email> (all offline tokens of the account), remote logout in the app (the ref of that PC), blocking or deleting the account, or the policy at 0. The PC learns it at its next reconnect (403) and wipes its locker; without internet only at the expiry date.

What is in the vault?

Small secrets per account and profile, encrypted on the server: the storage key of the encrypted profile folder (opslag-sleutel), Microsoft refresh tokens (ms-refresh:<32 hex>) and profile-folder generations (opslag-versie:<32 hex>). Only with a pc token; never the content in logs or the signed profile. Admin: vault <email> (contents never shown), vault-delete <email>.

Details

Pc token: 64 hex, valid token_duration (default 12 h); the server keeps only SHA-256 and the method. Not bound to the PC's IP (CGNAT, Wi-Fi to cable); the login session itself is bound to the IP.

What the PC checks in the profile (in this order, refusing everything on one error): first line ok and versie=2; handtekening= is the last line with 128 hex; the Ed25519 signature with the key from \EOS\FW\PROFILE.TXT (or the built-in production key); omgeving= and server= match; sessie= is its own session and pc= is SHA-256(own G); verloopt in the future when the clock is reliable.

Admin policy in the profile: the admin may add beheer=<console,sshd,log,profiel | geen> (admin-policy <email> …); it decides which admin commands a production PC allows. It cannot be written back by the PC.

Offline tokens: after POST /api/pc/login the profile contains (before token=) offline-dagen=<1..30>, offline-token=<64 hex> and account=<id>. The server keeps only the SHA-256 with account, profile kind, the pc token's ref and expiry (table offline_tokens). A reconnect gives a new profile with a new reconnect token; the old one expires. Reconnects are throttled per network (120/min) and per token (10/min).

Vault encryption: ChaCha20-Poly1305 under the server key from vault_key_file; associated data binds a row to user, profile, kind and key id. At most 9 secrets per profile; generations count separately (16, the oldest goes). Without vault_key_file all vault paths give 404.

Reference

CLI commands

CommandArgumentsWhat it does
pc-sessions—logged-in PCs
admin-policy<email> [<console,sshd,log,profiel> | geen | --delete]show/set/remove the admin policy in the signed profile; logs out the account's PCs
offline-policy[<*|@domain> <0..30>]show or set the offline policy
offline-policy-delete<*|@domain>remove a rule
offline-revoke<email>revoke all offline tokens of the account
offline-tokens—valid offline tokens (account, ref, profile)
vault<email>what the account has in the vault, and the vault log (never the content)
vault-delete<email>delete the account's whole vault

Legacy names: pc-sessies, beheer, offline-beleid, offline-beleid-wis, offline-intrek, kluis, kluis-wis.

Functions and modules

Function / moduleRole
euzos_profileserver::pc::sessionGET /api/session/<S>: creates, polls, revokes, delivers the profile
euzos_profileserver::pc::files, status, logout, settingsthe pc-token endpoints
euzos_profileserver::pc_login::loginpassword login on the PC (throttling, lockout)
euzos_profileserver::entra::loginMicrosoft ID-token login
euzos_profileserver::offlineoffline policy, offline tokens, reconnect, the offline-* CLI
euzos_profileserver::vault::set, fetch, delete_secret, listthe vault endpoints; Key::encrypt/decrypt
euzos_profileserver::settingswhitelist and validation of the settings writeback
euzos_profileserver::pairing_code, valid_session_idpairing code and session-id check
euzos_profileserver::webthe fallback web page /l/<S>
Kernel: kernel/src/profile.rs, libs/profilethe PC side (polling, checking, writeback)

Config files

Server configuration (profiel.conf):

KeyDefaultMeaning
qr_duration (legacy qr_duur)30 san unfetched login session
confirm_duration (legacy bevestig_duur)120 sa fetched session without approval
token_duration (legacy token_duur)43 200 s (12 h)the pc token
web_duration (legacy web_duur)3 600 sa sign-in on the web page
pc_password (legacy pc_wachtwoord)yespassword login on the PC
web_fallback (legacy web_terugval)yesthe web page /l/<S> without the app
allow_v1 (legacy sta_v1_toe)yes locally, otherwise nopolls without pc secret (the old 8.5 format)
vault_key_file (legacy kluis_sleutel_bestand)—vault key file; without it the vault is off
entra_client_id, entra_check_s (legacy entra_controle_s, default 900)—Microsoft login and offboarding check

On the PC: \EOS\FW\PROFILE.TXT (legacy name PROFIEL.TXT) with server=, environment=, key= (public key), optional key-id=, language= and private=off (legacy Dutch keys omgeving=, sleutel=, sleutel-id=, taal=, prive=uit are still read; euzos-profielserver key still prints that Dutch form). A production build uses its built-in server and key and only reads private= and language=.

On-disk config keys and typed confirmation words are English since 27-10-2026 (for example WIS-… → WIPE-…, omgeving= → environment=; docs/ENGLISH.md); the Dutch names stay accepted. The profile server's wire formats (pc line protocol, signed profile, signed phone messages, settings keys) stay Dutch.

API endpoints

MethodPathLegacy Dutch pathPurpose
GET/api/session/<S>?pc=<G>[&voorkeur=][&intrekken=1]/api/sessie/<S>QR login session (poll)
POST/api/pc/login/api/pc/inloggenpassword login
POST/api/pc/entra—Microsoft login
POST/api/pc/reconnect/api/pc/herverbindoffline → online
GET/api/files?token=/api/bestandenitem= lines of the profile
GET/api/status?token=—ok + verloopt=, or afgemeld + reden=
GET/api/logout?token=/api/afmeldenlog out the pc token
POST/api/profile/settings?token=/api/profiel/instellingenwrite back settings
GET/api/vault?token=/api/kluislist own kinds (no content)
PUT, GET, DELETE/api/vault/<kind>?token=/api/kluis/<kind>store, fetch, delete a secret
GET/l/<S>; POST /l/<S>/aanmelden, /l/<S>/bevestig; POST /uit— (user-visible paths)fallback web page
GET/api/preference/<S>/api/voorkeur/<S>the PC's preference for the web page

Request and response bodies are byte-identical on English and legacy routes.

Protocol messages and formats

Poll answers of GET /api/session/<S>:

wacht            + code=<6 digits> [+ gezien=1]
verlopen         + reden=tijd|geweigerd|ingetrokken|gebruikt|niet opgehaald|geen profiel
ok               + the signed profile (once)

The signed profile (status words and keys are Dutch wire values):

ok
versie=2
omgeving=sandbox
server=<internal-host>
sessie=<S>
pc=<SHA-256(G), 64 hex>
soort=zakelijk|prive
naam=<e-mail address>
weergavenaam=<display name>
kleur=<6 hex>
taal=<language>
<settings lines: balk=, thema=, recent=, browser-favoriet=, …>
item=<…>                        (0 to 64)
beheer=<policy>                 (only if set)
offline-dagen= / offline-token= / account=   (only after a password login, if allowed)
methode=wachtwoord|microsoft|offline         (not for a QR login)
token=<64 hex>
uitgegeven=<Unix time>
verloopt=<Unix time>
sleutel-id=<16 hex>
handtekening=<128 hex>

Signature: Ed25519 over "EUZOS-profiel-v2\0" || all bytes from ok up to and including the \n before handtekening=.

Password login (POST /api/pc/login, at most 2 KiB): 200 ok + profile; 400 reden=ongeldig; 401 reden=onjuist; 403 reden=account + status=…; 404 (off); 413 te_groot; 429 reden=te_vaak + wacht=; 503 reden=druk|database.

Microsoft login (POST /api/pc/entra): errors 400 ongeldig, 401 token/verlopen, 403 tenant/domein/account, 429 te_vaak, 503 sleutels|database|druk, 404 without entra_client_id.

Status (GET /api/status): ok + verloopt=, or afgemeld + reden=afgemeld|verlopen|onbekend; a database error is 503, never afgemeld.

Reconnect (POST /api/pc/reconnect, body offline-token=, sessie=, pc=): 200 + new profile, or 403 reden=ingetrokken|verlopen|geblokkeerd|gewist|uit|onbekend; also 400 ongeldig, 413 te_groot, 429 te_vaak, 503 database.

Settings writeback keys (whitelist): balk, balk-verbergen, taskbar-hide-maximized (on|off; deploy the server before kernels that send it), welkom, schermtoetsenbord, toetsenbord, toetsenbord-tik, thema, touchpad-natuurlijk, touchpad-tikken, touchpad-rechtsklik, touchpad-snelheid, touchpad-aanwijzer, muis-snelheid, muis-omwisselen, muis-wiel-omkeren, pointer-size, pointer-hide, aanraak-vegen, aanraak-doorrollen, aanraak-lang-drukken, screensaver, screensaver-wachttijd, screensaver-animatie, vergrendelen, recent, taal, kleur, browser-zoekmachine, browser-favoriet, browser-engine, browser-site, mail-account (settings::KEYS). screensaver-animatie takes logo|aurora|stars|clock; the legacy values sterren|klok are still accepted. A kernel from 27-10-2026 writes stars/ clock, so the profile server must be deployed first (an older server refuses those values). At most 48 KiB (settings::MAX_REQUEST = 49 152 bytes) and 104 lines (settings::MAX_LINES); an invalid line gives 400 and nothing changes.

Vault kinds: opslag-sleutel (created by the server on the first GET; PUT gives 403; DELETE = crypto-shredding), ms-refresh:<32 hex>, opslag-versie:<32 hex> (only upwards: lower gives 409 lager). Secrets at most 8 KiB.

See also

  • docs/PROFILE-PROTOCOL.md, "Logging in on a PC", "The format for EUZOS", "The vault", "Tokens and expiry", "Rate limiting"
  • docs/OFFLINE-LOGIN.md
  • docs/WORK-LOGIN.md
  • docs/ENVIRONMENTS.md
  • Phone app · Organisations · API · CLI