Skip to main content

Tideless QEA Demo

Goal: walk a single governed change through the Tideless QEA change-request flow on a non-Tide realm: make the change, watch it get captured, authorize it to threshold, then commit it.

This is the crypto-free governance mode: no Tide enclave, no signing, no approval popup. Approvals are recorded as the approving admin's username, and a commit is gated only by a threshold (number of approvals) plus an approver role. For what QEA is and why changes go through it, see the Admin Overview. For the Tide-provisioned (enclave) flow, see Setting Up and Using Tide QEA.

Assumptions

  • A running TideCloak with the QEA extension deployed.
  • A target realm that is not master (the master realm is always exempt from capture).
  • QEA enabled on the realm with the simple attestor (the default), the threshold set to 2, and an approver role (iga-approver) designated.
  • At least two distinct admins holding iga-approver plus manage-realm (here alice and bob). The same admin cannot authorize the same change request twice.

REST steps below assume:

KC=http://localhost:8080 # TideCloak base URL
REALM=my-realm # the target realm (not master)

Step 1: Make a governed change

Perform any governed write (create a user, create a role, grant a role, and so on). Here we grant a realm role to a user:

curl -i -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '[{"id":"'"$ROLE_ID"'","name":"some-role"}]' \
"$KC/admin/realms/$REALM/users/$USER_ID/role-mappings/realm"

Instead of applying, the server captures the change and returns 202 Accepted with a PENDING change request (CR):

HTTP/1.1 202 Accepted
Location: /admin/realms/<realm>/iga/change-requests/<CR_ID>
{ "status":"PENDING", "changeRequestId":"<CR_ID>",
"entityType":"USER", "actionType":"GRANT_ROLES" }

In the tide-console, the same action shows a toast and the new CR appears in the QEA Approvals inbox at 0 / 2, with its action type, the entity it affects, and the required approver role.

A captured Grant Roles change request in the QEA Approvals inbox (0/2)


Step 2: Authorize to threshold

Each approver opens the CR in QEA Approvals and clicks Authorize. One approval is recorded per admin; the count moves 0 / 2 then 1 / 2 then 2 / 2. Authorizing does not commit on its own until the threshold is reached.

As alice:

curl -s -X POST -H "Authorization: Bearer $TOKEN_ALICE" \
-H "Content-Type: application/json" -d '{}' \
"$KC/admin/realms/$REALM/iga/change-requests/$CR_ID/authorize"

As bob, authorize the same CR to reach 2 / 2:

curl -s -X POST -H "Authorization: Bearer $TOKEN_BOB" \
-H "Content-Type: application/json" -d '{}' \
"$KC/admin/realms/$REALM/iga/change-requests/$CR_ID/authorize"

Change request detail after the first authorization (1 of 2 signatures)

Two things to expect at this step:

  • An admin without iga-approver is refused with 403 Forbidden.
  • The same admin authorizing twice gets 409 Conflict. Distinct admins are required.

Step 3: Commit and verify

Once the CR is at 2 / 2, commit it. The change is replayed for real and the CR flips to APPROVED.

curl -s -X POST -H "Authorization: Bearer $TOKEN_ALICE" \
"$KC/admin/realms/$REALM/iga/change-requests/$CR_ID/commit"

In the tide-console, click Commit (or Authorize the already-approved CR). The change applies and the entity now appears for real: the granted role shows up on the user.

After commit: the granted role now shows on the user's Role mapping

If commit fails:

  • 412 Precondition Failed: still under threshold. Get another distinct approver-role admin to authorize.
  • 403 Forbidden: the committing admin lacks the approver role.
  • 409 Conflict: the CR is no longer PENDING (already committed or denied).

Next steps