Skip to content

Authorization Requests

eric edited this page Jun 12, 2026 · 1 revision

Authorization Requests

The authorization flow is how a new client gets a token without anyone ever pasting shared secrets around: the client asks, a manager approves, the server issues.

1. The client submits a request

npm run auth:request -- \
  --realm acme \
  --role producer \
  --client-id machine-042 \
  --client-name "Machine 042"

This prints a generated client_token and a request_id. Programmatically:

const { Authorization } = require('tyo-mq');

const submitted = await Authorization.submitAuthorizationRequest({
    realm: 'acme',
    role: 'producer',                 // producer | consumer | both | manager | admin
    client_id: 'machine-042',
    client_name: 'Machine 042',
    client_token: 'a-token-the-client-generated',
    challenge_response: { ticket: 'INC-123' }   // optional out-of-band proof
}, { host, port, protocol });

Only the latest pending request per (realm, client_id) is kept — a re-submitted request supersedes the previous one.

2. A manager reviews and decides

npm run auth:manager -- next
npm run auth:manager -- approve <request_id> --role producer
npm run auth:manager -- reject  <request_id> --reason "unknown client"

Or via the interactive Manager Tools, or as library calls (nextAuthorizationRequest / decideAuthorizationRequest).

The manager's response never exposes the raw client token — only a hash. And the manager's own credential never leaves their machine: every command is signed (HMAC-SHA256 over action + body + timestamp + nonce), nonces are single-use, and proofs expire after 5 minutes. In a cluster, nonces are single-use across all nodes.

3. Approval takes effect

On approval, the client's token is added to the server's auth token list (persisted to the settings file when one is configured, and synced cluster-wide), and the waiting client receives:

AUTHORIZATION_APPROVED { request_id, realm, role }

It can then authenticate normally with its token. Rejection sends AUTHORIZATION_REJECTED { request_id, reason }.

Realm-scoped managers

A realm operator who shouldn't hold the global admin token can be given a realm manager key (auth.realms.<realm>.manager_key, or the set_realm_manager_key command). That key can:

  • poll and decide authorization requests for its own realm only
  • nothing else — server-wide management still requires the admin token
TYO_MQ_REALM_MANAGER_KEY="realm-operator-secret" \
  npm run auth:manager -- next --realm acme

Revocation

# by realm + client id, or by token hash
npm run manager        # option 14, or:
await Authorization.authManagementCommand(adminToken, {
    command: 'revoke_token',
    realm: 'acme',
    client_id: 'machine-042'
}, options);

Revocation takes effect immediately for new connections and is persisted / cluster-synced like any settings change.

In a cluster

Requests live in the shared Redis document: submit through any node, poll and decide from any node — the requester is notified on whichever node holds its socket. See Clustering.

Clone this wiki locally