How It Works
How It Works
Login Flow (DDISA)
User enters email at SP
↓
SP extracts domain → DNS lookup: _ddisa.example.com
↓
Discovers IdP URL → Redirects to IdP /authorize
↓
User authenticates with Passkey (or Agent via Ed25519)
↓
IdP issues authorization code → Redirect back to SP
↓
SP exchanges code for signed JWT (backchannel)
↓
SP validates JWT (issuer, audience, signature, nonce, act)
↓
User is logged in ✅
This is a standard Authorization Code + PKCE flow, enhanced with DNS-based IdP discovery and Passkey-only authentication.
Grant Flow (Permissions)
When an agent needs to perform a privileged action:
1. Agent Requests a Grant
POST /api/grants
{
"requester": "agent@example.com",
"target": "prod-server",
"grant_type": "once",
"permissions": ["deploy"],
"reason": "Deploy hotfix #123"
}
2. Human Reviews
The agent's owner or designated approver sees the request in the web UI (or via notification) and approves or denies it.
3. Agent Receives AuthZ-JWT
On approval, the agent can request a signed AuthZ-JWT:
{
"sub": "agent@example.com",
"act": "agent",
"aud": "prod-server",
"grant_type": "once",
"permissions": ["deploy"],
"decided_by": "alice@example.com",
"exp": 1234567890
}
4. Target Verifies
The target system validates the AuthZ-JWT: signature, audience, expiry, permissions, and optionally cmd_hash for exact command binding.
escapes — Privilege Elevation for Agents
escapes is a Rust binary that brings the grant flow to local privilege elevation. It supports multiple agents per machine, each with their own user-owned Ed25519 keypair.
escapes --grant <jwt> -- systemctl restart nginx
- Loads config (as root), then drops privileges to real user
- Loads private key from configured path (as user), derives public key
- Matches public key against registered agents in config
- Authenticates to the matched agent's IdP via Ed25519
- Creates a grant request (with SHA-256 hash of the command)
- Waits for human approval
- Receives AuthZ-JWT, verifies
cmd_hashmatches - Re-elevates to root, sanitizes environment, executes command
The binary runs with the setuid bit — it starts as root, drops privileges before key loading, and only re-elevates after JWT verification.