The admin console
How operators reach a company's console, the session it opens, and the rules every change follows: a role, a reason, an idempotency key, a typed confirmation where a change is wide, and masked addresses.
Each company has an admin console at <ADMIN_URL>/admin/<company>/, served by
the binary on its own listener and origin, apart from the issuers. It holds no
token, only a session cookie, and asks its API for everything it shows. It offers
the sections the operator's roles can use: Users, Groups, Clients, Operators,
Sign-in policy, Branding, Mail, Signing keys, Audit trail, and Companies in the
system console. The API refuses the rest whatever is offered.
Signing in to the console
An operator opens <ADMIN_URL>/admin/<company>/signin, which sends the browser to
that company's own sign-in as the client admin-console, with PKCE, a state and
a nonce. Every company has this client registered with no grant type, so
nothing outside the server can redeem its codes, and its consent page is always
shown. The return to <ADMIN_URL>/admin/<company>/callback opens a console session
only when:
- the
state, the issuer, the code and itsnonceall check out; - the operator signed in with two factors;
- they hold at least one current operator role.
Any other return gets one and the same refusal and is recorded.
The console session
The session is an HttpOnly, SameSite=Strict cookie (__Host- and Secure
over https). It lasts at most 8 hours, ends after 30 minutes unused, and ends with
the company sign-in session it came from or when the operator's last role is
taken away. GET <ADMIN_URL>/admin/<company>/api/me names the operator and their
roles; POST <ADMIN_URL>/admin/<company>/signout ends the session. Console
requests are counted per client address under the sign-in limit.
Operator roles
Roles are held per company and per task:
| Role | Lets an operator |
|---|---|
users | read and open accounts, issue enrolment codes, reveal an address, disable and enable accounts, manage groups |
clients | register and remove clients |
policy | change the two-factor and registration policy, branding and mail wording |
keys | rotate and withdraw signing keys |
audit | read the audit trail |
companies | create, suspend and resume companies; only system users hold it |
Holding a role is what lets an operator give it (see Users, groups and operators).
How a change is made
- It comes from the console's own origin as JSON carrying the operator's
reason(1 to 500 characters) and anIdempotency-Keyheader (16 to 128 letters, digits,-or_). - It is made once per operator and key: sent again within a day it gets the first answer back, and the same key with another change is refused.
- It is recorded as
admin_actionwith the operator, the role, the change and the reason. - A change that replaces a policy or a stored value names the revision it read and
is refused as
changed_meanwhilewhen another change came first. - The page asks before a wide change: disabling an account names it and says what ends; removing a client says how many users hold a grant to it and asks for its id typed out; deleting a group says how many members it has; a two-factor policy change, a registration change or a company's suspension asks for the company id typed out; withdrawing a key asks for its id.
Lists page behind the server's cursor with no total, and an address is shown masked until it is revealed with a reason.
Sign-in policy
GET and PUT <ADMIN_URL>/admin/<company>/api/policy/two-factor (role policy)
read and change the company's two-factor policy, off, optional or required;
a change names the policy it replaces in expected. What each setting does to a
sign-in is in Authorization
and The account portal.
GET and PUT <ADMIN_URL>/admin/<company>/api/policy/registration read and
change whether people may open their own account: {revision, open, domains, reason}, where domains lists up to 20 domains and an empty list means any
address.
What it does not do yet
Stated as limits rather than promised: a change that reaches a whole company is
made by one operator, with no second approval; the roles given by
bootstrap-operator do not expire; a company made in the system console gets
its first operator only through bootstrap-operator --company; and changing a
client's registration is not in the console.