Client security requirements
Every approved client meets these requirements (REQ-XCH-027). They are checked when a client applies (see onboarding) and again for every release that changes how it signs in or stores credentials.
Sign-in #
How each step works is on the authentication page.
- Use the OAuth 2.0 device authorization grant (RFC 8628) against the pinned production issuer
https://profit-base.online/auth/realms/iri, with your registered public client id and no client secret. - Show the
user_codeand the bareverification_uri, and let the member type the code in their browser. Never open, show or sendverification_uri_complete, not even as a QR code: it skips the page where the Basetool warns about device-code phishing. - Bind every token to a DPoP key (RFC 9449, ES256): prove possession at the token endpoint and on
every API call, and retry once with the server’s
DPoP-Nonce. - Pin the production issuer. Another issuer — the local sandbox — may be selected only through a developer environment variable, never in the user interface: a user-facing issuer switch would be a phishing lever.
- Request
exchange.connectand only the scopes of the features the member enabled. - Label each installation (
POST /exchange/v1/me/installation) so the member can tell two devices apart and disconnect one of them. The label is at most 40 characters of letters, digits, spaces, the ASCII hyphen-minus-,_and., not starting with a space — no en dash, no other punctuation — and it is never an automatic host or computer name.
Credential storage #
- Keep the refresh token and the DPoP private key only in the platform’s secret store: Windows
Credential Manager or DPAPI, with the key non-exportable in CNG where available; on Linux the
Secret Service, or — only where it is unavailable — a file readable by the user alone (
0600), in a directory only the user can open (0700), with a visible hint that it is used. - Never write a token or a key into a log, a backup, a diagnostics bundle, a problem report or any
channel that leaves the device. Redact
AuthorizationandDPoPheaders and anything shaped like a JWT from everything you collect. - “Disconnect” revokes the refresh token (RFC 7009) and deletes the stored credential.
Data #
- Send only the signed-in member’s own data, and never purchase data, account ids or other members’ data. The RSI handle goes only to the account check.
- Store the org demand for at most 7 days, outside cloud-synced folders, never in backups or diagnostics, and never forward it.
- Send a descriptive
User-Agent: product, version and a URL, for exampleExampleClient/1.2.0 (+https://example.org/client).
Sync behaviour #
The sync guide explains each rule; these are the ones an application is checked against:
- Every resource is an explicit opt-in of the member and off by default.
- Pull before push; the first sync of a resource is add-only; a
removeis sent only from a diff against the last synced state. - Never re-add what the member removed elsewhere: a
REMOVED_ELSEWHEREis shown to the member, andoverrideis sent only after the member agreed. - Ships are linked to the member’s existing ships before any new one is created.
- After
410 CURSOR_EXPIRED, reconcile a fresh snapshot against the last synced state; it is not an add-only first sync. - Stock is sent as lots with the
expectedQuantitylast seen; aVERSION_CONFLICTis resolved by pulling, never by resending blindly. - Before the first sync of a newly detected game account, run the account check and warn the member
on
mismatch. - The baseline, the ship links and the feed cursors are kept per installation, keyed by its
installationId, and never shared with another installation — not through a shared data folder either (several installations). - Every
Idempotency-Keyis random, such as a UUID, and used for one logical write only. - When a change result reports
detachedFromMissions,offersReducedoroffersRemovedabove 0, the member is shown what happened (ships, stock). - Every ship
upsertsends the ship’s currentnameandlocation— the server’s, or the member’s change to them — because anupsertclears an omitted one (ships). - Retries back off from 5 seconds, doubling up to at most 5 minutes, with random jitter, and never
wait less than the answer’s
Retry-After(back-off). - Syncs run on start and after a local change, and a timed sync at most every 5 minutes (sync cadence).
Response and supply chain #
- Publish a privacy statement and a security contact.
- Publish a fixed release within 7 days of a reported token-handling flaw; otherwise the client is suspended or restricted by a minimum version.
- Code signing of releases is recommended, not required.