For state-changing operations (POST, PUT, DELETE), the X-DFNS-USERACTION header proves the caller controls a registered credential:
Client requests a challenge from DFNS
Client signs the challenge with their credential (passkey or asymmetric key)
DFNS verifies the signature matches a registered credential
This ensures that even if a token is stolen, an attacker cannot perform sensitive operations without the credential.The challenge you sign binds the exact request you are authorizing: a hash of the request body, the HTTP method, the path, and a server-generated human-readable summary of the action (for example, “Transfer Native asset to recipient 0x…”). DFNS recomputes and re-verifies these when you submit the signed action, so a request that no longer matches what was signed (different recipient, amount, path, or method) is rejected. Your signature is bound to a specific intent, not just to “some request.”
After authentication, DFNS checks if the user has permission to perform the requested action.Permissions follow a whitelist model - users can only perform actions explicitly granted:Example: A user with Wallets:Read can view wallets but cannot transfer assets (requires Wallets:Sign).See Permissions for the full list.
The layers above describe how a single request is authorized. This section describes who you have to trust, and how to verify operations independently of that trust.DFNS operates as the maker: it builds the transaction from your request and submits it to the signers. You can operate as the checker: you independently verify what is about to be signed, and approve or reject it. A checker step lets you detect a tampered transaction in both directions:
If DFNS were compromised, your checker sees a transaction that does not match the intent you authorized, and rejects it.
If your initiating workstation were compromised, the transaction is checked again before signing, so tampering is caught even though it originated on your own machine.
This is distinct from separation of duties within your organization, where the initiator and the approver are different members of your team (see govern wallet access). Trust boundaries are about verifying DFNS and your own endpoints, not only your team members.DFNS gives you two places to insert a checker:
A policy with RequestApproval holds the operation and notifies an approver with the transaction details. The approver is a human reviewing on a separate device, or a service account running your own automated checks. They approve or reject out of band.
Self-hosted signers call an HTTP handler you control before signing, passing a digest of the payload to be signed plus key details. Return 200 OK to allow, anything else to reject.
Each row assumes the worst case at one location and shows which checker catches a tampered transaction.
Assume compromised
Example
What catches it
Your workstation, browser, or local UI
The UI shows “send 1 BTC to B” but submits “send 1 BTC to X”
DFNS builds the transaction from the request it received. A policy approver reviewing on a separate device sees recipient X and rejects. A validation gate handler can compare the signing request against the transaction your systems expect and reject the mismatch. A trusted display lets the operator catch X at signing time.
DFNS
You authorize “send to B” but DFNS builds “send to X”
A checker running on your own infrastructure detects that the transaction does not match the intent you authorized, and rejects it before or at signing.
Your own checker infrastructure
Your validation gate handler and approver are both compromised
DFNS is healthy and builds the transaction faithfully from the intent you authorized, so “send to B” stays “send to B”.
No single party, whether DFNS, your workstation, or your checker, can unilaterally produce a malicious signed transaction without another layer detecting it.
The human-readable summary bound into the user action signature is what makes “what you see is what you sign” (WYSIWYS) possible: the operator signs a description of the action, not an opaque blob. For this to defend against a compromised client, the summary must be shown to the operator on a surface that the client’s own code cannot alter. The standards for this in the browser, such as Secure Payment Confirmation, are still emerging and support is currently limited.