File size: 3,746 Bytes
a6a5d8e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# WebAuthn Human-in-the-Loop Attestation Integration Notes

## Standards References
- **W3C WebAuthn Level 3**: https://www.w3.org/TR/webauthn-3/
- **FIDO2 CTAP2**: https://fidoalliance.org/specs/fido-v2.0-ps-20190130/
- **Yubico Signing Pattern**: https://developers.yubico.com/WebAuthn/Concepts/Using_WebAuthn_for_Signing.html
- **COSE Algorithms**: https://www.iana.org/assignments/cose/cose.xhtml
- **SimpleWebAuthn**: https://simplewebauthn.dev/docs/

## Architecture
```
Cursor/Claude operator interface
         │ sensitive action detected
         ▼
mcpWebAuthnApprove() → returns AuthenticationOptions to browser
         │
         ▼
Browser: startAuthentication() from @simplewebauthn/browser
Touch ID / FIDO2 gesture
         │
         ▼
WebAuthn assertion (clientDataJSON + authenticatorData + ECDSA-P256 sig)
         │
         ▼
verifyAssertionAndEmitDSSE() → WebAuthnDSSESignature
         │
         ▼
augmentDSSEWithWebAuthn() → DSSE envelope with 2 signatures:
  1. HMAC-SHA256 (automated, machine identity)
  2. WebAuthn ECDSA-P256 (human, biometric/PIN-bound)
         │
         ▼
augmentReceiptWithWebAuthn() → JSONL receipt + humanAttestation block
         │
         ▼
submitDSSEToRekor() → Rekor entry with dual-signature envelope
```

## MCP Tool Integration

Two new MCP tools exposed to Cursor/Claude users:

### `webauthn_register`
```typescript
server.tool("webauthn_register", {
  operatorDID: z.string(),
  userName: z.string(),
}, async ({ operatorDID, userName }) => {
  const opts = mcpWebAuthnRegister(szlRP, operatorDID, userName);
  // Return to browser for startRegistration(@simplewebauthn/browser)
  return { registrationOptions: opts };
});
```

### `webauthn_approve`
```typescript
server.tool("webauthn_approve", {
  operatorDID: z.string(),
  receiptId: z.string(),
}, async ({ operatorDID, receiptId }) => {
  const receipt = await lookupReceipt(receiptId);
  const opts = mcpWebAuthnApprove(szlRP, operatorDID, receipt.envelope.payload);
  // Return to browser for startAuthentication()
  // After browser completes gesture, call verify_assertion tool:
  return { signingOptions: opts, pendingApproval: receiptId };
});
```

## Sensitive Action Policy (when to require WebAuthn)
Configure in `a11oy/src/webauthn/policy.ts`:

| Action | Require WebAuthn? | Reason |
|---|---|---|
| `deploy` to production | YES | Irreversible side effect |
| `key_rotation` | YES | Cryptographic identity change |
| `federation_cross_ref` | YES | Cross-org trust boundary |
| `validate` | NO | Automated quality gate |
| `audit_export` | YES | Data sovereignty |
| `deploy` to staging | NO | Reversible test env |

## STAGED-ADVISORY: Production Dependencies

```bash
# Server-side (Node.js Pepr/MCP):
npm install @simplewebauthn/server

# Browser-side (Cursor plugin / web UI):
npm install @simplewebauthn/browser

# Replace dev stubs:
# verifyRegistration → verifyRegistrationResponse from @simplewebauthn/server
# verifyAssertionAndEmitDSSE → verifyAuthenticationResponse from @simplewebauthn/server
```

## Security Properties
1. **Human presence**: UP flag verified — physical authenticator interaction required
2. **User verification**: UV flag verified — biometric/PIN required, not just tap
3. **Replay prevention**: signCount monotonically increasing; counter replay rejected
4. **Payload binding**: challenge = SHA-256(DSSE payload) — assertion is cryptographically
   bound to the specific receipt being approved, not just any receipt
5. **Origin binding**: clientDataJSON.origin checked — prevents cross-site relay attacks
6. **Additive, not substitutive**: WebAuthn sig appended alongside HMAC; both required
   for "dual-control" governance actions