# Account Abstraction on EVMs Source: https://docs.dfns.co/advanced/account-abstraction-on-evms The following article is relevant primarily for EVM compatible networks. ## Overview Ethereum and other Ethereum virtual machine (EVM) compatible networks require transactions to be originated from an externally owned account (EOA) and for that account to pay the gas fees for the transaction in the native cryptocurrency of the chain (for example, Ether in the case of Ethereum). Blockchain users pay gas in order to purchase scarce block space and fund the chain, incentivizing validators to participate in securing the network. For projects operating primarily over tokens or NFTs, however, requiring a native cryptocurrency balance to fund transactions introduces onboarding friction. Additionally, ensuring end-user wallets are sufficiently funded to execute transactions creates ongoing operational overhead. For these reasons, the notion of “gasless” or "sponsored" transactions has been an area of ongoing debate for a number of years. Unfortunately, the Ethereum community has failed to settle on a single standard nor enshrined this capability in the layer 1 protocol, leaving developers to contend with various approaches and weigh trade-offs depending on their specific use case. Various approaches to achieving sponsored transactions are outlined below. ## Account Abstraction (ERC-4337) One of the newest approaches to enabling sponsored transactions on EVM chains is to use paymasters as specified in [ERC-4337](https://www.erc4337.io/), Account Abstraction (AA). AA separates (or abstracts) authentication against smart contract wallets from the requirements of the underlying protocol (specifically ECDSA/secp256k1 signatures). Additionally, it specifies standards for executing sponsored transactions using smart contracts called paymasters. Transactions in AA are encapsulated in a higher level format called user operations and submitted to an off chain network of bundlers which batch and send them to the chain through a singleton entry point contract. Every user operation must be signed before it can be submitted to the chain. Increasingly, Dfns customers are relying on our advanced MPC solution to ensure secure and highly available signing of user operations. The Dfns engineering team has built proofs of concept (POCs) to demonstrate how to integrate our MPC signing with various partners offering AA platforms. ### Biconomy Biconomy is a web3 infrastructure provider offering a full stack solution for AA. You can read about their solution [here](https://www.biconomy.io/smart-accounts). Dfns has built a sample integration which processes a gasless transaction on the Mumbai testnet. You can find a Readme and the full code [here](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem/biconomy-aa-gasless) as well as in the Biconomy documentation [here](https://docs.biconomy.io/account/signers/dfns). ### Safe In addition to being the industry-leading Smart Account, Safe also supports ERC-4337 via Modules and the FallbackHandler with a flow documented [here](https://docs.safe.global/home/4337-safe). The [Safe4337Module](https://github.com/safe-global/safe-modules/blob/main/modules/4337/contracts/Safe4337Module.sol) extends the Safe Smart Account to enable ERC-4337 compliant transactions, received via the proxy contract. This functionality is exposed via the Relay Kit in the Safe SDK - check [this guide](https://docs.safe.global/home/4337-guides/safe-sdk) on how to integrate it. To use Dfns with Safe AA, simply use our [Generate Signature API](/api-reference/keys/generate-signature) to sign User Operations sent through your bundler to the Safe proxy. ### ZeroDev ZeroDev is a 4337 provider offering Bundler and Paymaster services as described in [their docs](https://docs.zerodev.app/). Dfns has built a sample integration demonstrating a sponsored transaction using our viem wrapper which is available [here](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem/zerodev-aa-gasless). Follow [their quickstart](https://docs.zerodev.app/sdk/getting-started/quickstart) to begin an integration. ## Meta-Transactions (ERC-2771) Meta-transactions are an earlier attempt to enable sponsored transactions as specified in [ERC-2771](https://eips.ethereum.org/EIPS/eip-2771). In this approach, end user transactions are forwarded off-chain to relayers that fund gas cost in exchange for a fee. The primary caveat is the target contract must support the standard by implementing the [ERC2771Context](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/metatx/ERC2771Context.sol) interface which replaces the built in msg.sender variable with a \_MsgSender() function. This implementation extracts the original sender from the call data to prevent the relayer address from being used in its place. If you control the target smart contact and can support this interface or if you have validated your target contract already supports 2771, there are a number of relayer providers you can work with in order to sponsor transactions on behalf of your users and provide a gasless user experience while signing transactions with Dfns. The following are a few examples. ### Open Gas Station Network (GSN) GSN is an open-source public good funded by the Ethereum Foundation and built by the authors of ERC-2771 to help promote the standard. They offer detailed [documentation](https://docs.opengsn.org/) on configuring a relayer and have published a sample ["capture the flag" workshop](https://github.com/opengsn/workshop) to demonstrate the changes required to make a smart contract compatible with 2771. They even have a [detailed tutorial on setting up a relay server](https://docs.opengsn.org/relay-server/tutorial.html#introduction). You can reach out to the GSN team in [discord](https://discord.gg/NXXTCbh58s) with any questions. ### Biconomy Biconomy is one of the longest standing players in the relayer market. They offer [meta-transaction support](https://docs.biconomy.io/) to enable sponsored transactions using the ERC-2771 standard. Their documentation covers implementing gasless transactions and enabling smart contracts for 2771 support. Feel free to reach out to the Biconomy team through their [documentation site](https://docs.biconomy.io/) with any questions specific to their offering. ### Gelato Network Gelato describes themselves as "web3’s decentralized backend" and provides a number of services to enhance smart contracts, including 2771 compatible relayers. They expose a centralized funding service called [1 Balance](https://docs.gelato.network/developer-services/1balance). Once an account is funded, it can be used to sponsor transactions on behalf of users by implementing [sponsoredCallERC2771](https://docs.gelato.network/developer-services/relay/erc-2771-recommended/sponsoredcallerc2771) as detailed in their documentation. Please contact Gelato directly with questions pertaining to their specific configuration. ## Automated "Gas Tanks" The final approach to enabling gasless transactions is simply to transfer the required amount of the native cryptocurrency into each end users' wallet, relieving them from the responsibility of acquiring it themselves. In most cases, implementations of this approach specify a "gas tank" wallet which automatically sends cryptocurrency to other wallets when they fall below a given threshold. The primary problem with this approach is the cost of sending each individual "refuel" transaction on chain. Looking at the economics on the Ethereum L1, it does not scale well as demonstrated in the calculations below: ## Next Steps Check out how Dfns has implemented [Fee Sponsorship](/features/fee-sponsors)! If you're interested in implementing sponsored transactions or have a novel approach to the problem, don't hesitate to reach out to us as this is one of our favorite topics of discussion. As always, feel free to send on [https://support.dfns.co](https://support.dfns.co). # Credentials Source: https://docs.dfns.co/advanced/credentials In order to [login](/api-reference/auth/login-flows), or [sign their Actions](/api-reference/auth/signing-flows), users need to sign "challenges" using their Credentials. A Credential is essentially a public/private cryptographic keypair. The private key is held by the user, while the public key is provided to Dfns to register the credential for the user. The first time you registered on Dfns dashboard, you created a Passkey credential (see how [here](/introduction/quickstart/1-create-your-organization-and-invite-employees)). You can also register additional credentials later on (see how [here](/guides/registering-a-new-passkey-credential)). Different kinds of Credentials can be created, depending on your use case, and how you prefer to manage them: * Fido2 Credentials (aka "Passkeys" / "WebAuthn") -> Uses WebAuthn standard to create/manage passkeys on your device (see more about that below). You can use passkeys if you need a client-side User signature (eg. in a web app / native app). * Key Credentials -> "manually" generate keypairs yourself, and store them however you see fit (see [How to generate a keypair](/guides/developers/generate-a-key-pair)). You can use Key Credential if you need a Service Account sitting in your server to also be the signer for example. Depending on the Identity you are using, the Credentials supported are such: | Identity | WebAuthn Credentials | Key Credentials | | --------------------------- | -------------------- | --------------- | | User | ✅ | ✅ | | PAT (Personal Access Token) | 🛑 | ✅ | | Service Account | 🛑 | ✅ | ## User Credentials - Passkeys Users can register with a WebAuthn Credential (aka "Passkey") or with a raw Public/Private Key Passkeys is the common term used to describe the Fido2 standard called "WebAuthn". It is a web authentication standard supported by most modern browsers, phones and devices, which leverages your devices key-management features (like touch ID on a mac, a phone authenticator, a yubikey, some password managers support creating and storing passkeys, etc). Those passkeys can then be used by the user to sign payloads when needed. Here's some screenshots with some examples of WebAuthn prompts shown in your browser during Credential creation, or during Signing using those Credentials. Below is an example of the promps a user can see on a web app, when a challenge needs to be signed with the passkey: it's asking the user for his biometrics (fingerprint) before using the passkey to sign. You can read more about WebAuthn on [webauthn.guide](https://webauthn.guide/), and if you want you can test a WebAuthn demo on [webauthn.io](https://webauthn.io/) ## Machine Credentials - Asymetric Keys When registering a new long-lived access token (Service Account or Personal Access Token) to be used by a backend, you need to link a public-private key pair to your token. This is done by passing a public key with the API call. See [Generate a Key Pair](/guides/developers/generate-a-key-pair) for information about how to generate a key pair. ### Public Key Format Public Keys need to be formated with PEM encoding. #### PEM Encoding PEM encoding base64 encodes the public key data and places it between a header and footer. The header and footer can be slightly different depending on the crypto library you use, but it will always have the same basic format: ``` -----BEGIN PUBLIC KEY----- -----END PUBLIC KEY----- ``` For example ``` -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYsHwe62PxDXIXjvSd0/ZdndtvenLqZ6u62pp2/SejCs4NuJ5fOCsUDzqFXxBNJpA9CkFnqASaKP9n4N3XgQ1mQ== -----END PUBLIC KEY----- ``` #### Converting from raw to PEM Some crypto libraries do not support PEM format. If your library supports exporting to SPKI you can export the key into SPKI format, base64 encode that value, and place it inside the header and footer. ```javascript JavaScript (Web Crypto) theme={null} function arrayBufferToBase64(buffer) { const bytes = new Uint8Array(buffer) return btoa(String.fromCharCode(...bytes)) } async function exportPublicKeyInPemFormat(key) { const exported = await crypto.subtle.exportKey('spki', key) const pem = `-----BEGIN PUBLIC KEY-----\n${arrayBufferToBase64(exported)}\n-----END PUBLIC KEY-----` return pem } ``` ```python Python theme={null} from cryptography.hazmat.primitives import serialization def export_public_key_in_pem_format(public_key) -> str: """Export a public key to PEM format.""" pem_bytes = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) return pem_bytes.decode('utf-8') ``` ### Registering a key pair When registering a user with a private key, you need to: 1. Get a registration challenge from the Dfns API 2. Create the key pair locally 3. Sign the registration challenge and public key 4. Return the signed challenge to the Dfns API #### The Registration Challenge A registration challenge is returned from calls to: * /auth/registration/init * /auth/registration/delegated * /auth/credentials/init In all cases the challenge format is the same. You will recieve an object with the following properties (additional properties exist for managing credentials with WebAuthn): | field | description | | ------------------------------ | -------------------------------------------------------------------------------------- | | `challenge` | A string that will be signed with the new credential | | `temporaryAuthenticationToken` | A JWT that is passed to the registration endpoint to identify the registration session | | `supportedCredentialKinds` | The list of credential types that are supported, should always contain "Key" | #### How to Sign the Challenge with the Private Key The user signs the challenge to prove they are in possession of the key being registered. The user will also sign the public key to ensure the key is not replaced when transmitted to Dfns. ##### Client Data The user needs to format the challenge into a [Client Data object](/api-reference/auth/credentials-data#client-data). ##### Attestation Data The client data object is then used to build the [Attestation Data object](/api-reference/auth/credentials-data#attestation-data). ##### Signing Example: First factor and Recovery credentials: ```typescript TypeScript theme={null} recoveryClientData = { type: 'key.get', challenge: base64url(JSON.stringify({ "firstFactorCredential":{ "credentialKind":"Key", "credentialInfo":{ "credId":"6Ca6tAOFTx2odyJBnCoRO-gPvfpfy0EOoOcEaxfxIOk", "clientData":"eyJ0eXBlIjoia2V5LmNyZWF0ZSIsImNoYWxsZW5nZSI6...", "attestationData":"eyJwdWJsaWNLZXkiOiAiLS0tLS1CRUdJTiBQVUJMSU..." } }, "recoveryCredential":{ "credentialKind":"RecoveryKey", "credentialInfo":{ "credId":"GMkW0zlmcoMxI1OX0Z96LL_Mz7dgeu6vOH5_TOeGyNk", "clientData":"eyJ0eXBlIjoia2V5LmNyZWF0ZSIsImNoYWxsZW5nZSI6...", "attestationData":"eyJwdWJsaWNLZXkiOiItLS0tLUJFR0lOIFBVQkxJQ..." }, "encryptedPrivateKey":"LsXVskHYqqrKKxBC9KvqStLEmxak5Y7NaboDDlRSIW7..." } })), origin: this.appOrigin, crossOrigin: false, } const clientData = Buffer.from(JSON.stringify(recoveryClientData)) const signature = crypto.sign(undefined, clientData, newKey.privateKey) ``` ```python Python theme={null} import json import base64 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec def to_base64url(data: bytes) -> str: return base64.urlsafe_b64encode(data).rstrip(b'=').decode() recovery_client_data = { "type": "key.get", "challenge": to_base64url(json.dumps({ "firstFactorCredential": { "credentialKind": "Key", "credentialInfo": { "credId": "6Ca6tAOFTx2odyJBnCoRO-gPvfpfy0EOoOcEaxfxIOk", "clientData": "eyJ0eXBlIjoia2V5LmNyZWF0ZSIsImNoYWxsZW5nZSI6...", "attestationData": "eyJwdWJsaWNLZXkiOiAiLS0tLS1CRUdJTiBQVUJMSU..." } }, "recoveryCredential": { "credentialKind": "RecoveryKey", "credentialInfo": { "credId": "GMkW0zlmcoMxI1OX0Z96LL_Mz7dgeu6vOH5_TOeGyNk", "clientData": "eyJ0eXBlIjoia2V5LmNyZWF0ZSIsImNoYWxsZW5nZSI6...", "attestationData": "eyJwdWJsaWNLZXkiOiItLS0tLUJFR0lOIFBVQkxJQ..." }, "encryptedPrivateKey": "LsXVskHYqqrKKxBC9KvqStLEmxak5Y7NaboDDlRSIW7..." } }).encode()), "origin": app_origin, "crossOrigin": False, } client_data = json.dumps(recovery_client_data, separators=(',', ':')).encode() signature = private_key.sign(client_data, ec.ECDSA(hashes.SHA256())) ``` # Delegated wallets Source: https://docs.dfns.co/advanced/delegated-wallets Give your users full ownership of their wallets while you provide the infrastructure. ## What is a delegated wallet? A delegated wallet is a wallet where **your end user has full control**, not your company. Think of it like giving someone the only key to a safe deposit box - you provide the box, but only they can open it. When you delegate a wallet: * Only your user can move funds or sign transactions * Your company cannot access the wallet's assets * Your user proves ownership using biometrics (Face ID, fingerprint) or a security key ## Why delegate wallets? ### Regulatory clarity With delegated wallets, your company does not have custody of user funds. This can simplify regulatory requirements since you're providing infrastructure, not holding assets on behalf of users. ### User trust Users have cryptographic proof that only they control their wallet. Your company physically cannot move their assets without their explicit approval. ### Reduced liability Since you cannot access user funds, you're not responsible for securing them against internal threats or being a target for attacks seeking to compromise user assets. ## How it works ### Architecture Dfns uses distributed key generation and threshold signatures to secure wallets. Private key shares are encrypted and stored across a decentralized signer network spread across multiple data centers and geographic regions. The wallet private keys never leave Dfns infrastructure - they are not stored on the user's device. ```mermaid theme={null} flowchart LR subgraph user["User's Device"] passkey["🔐 Passkey"] end subgraph your["Your Infrastructure"] app["Your App"] end subgraph dfns["Dfns"] api["API"] signers["Distributed Signers"] end passkey -->|"Signs request"| app app -->|"Authenticated request"| api api -->|"Coordinates signing"| signers ``` The key insight is that **control of the API becomes proof of custody**. This control requires both an access token and a signing credential (passkey). In a delegated configuration, the signing credential lives on your user's device - meaning only they can authorize transactions. This is different from traditional self-custody solutions like MetaMask or Ledger, where users must secure a seed phrase. With Dfns delegated wallets: * Users authenticate with familiar biometrics instead of seed phrases * If a credential is compromised, it can be revoked * If a credential is lost, it can be recovered ### Transaction flow 1. **User signs up** - They register with your app and set up a passkey (biometric or security key) 2. **Wallet is created** - Your system creates a wallet and delegates it to the user 3. **User transacts** - When they want to send funds, they approve with their biometric 4. **You can't intervene** - Your company has no ability to approve or block their transactions ## User experience From your user's perspective, delegated wallets feel like any modern app: * Sign up with email or social login * Approve transactions with Face ID or fingerprint * No seed phrases to write down or remember * Can recover access if they lose their device ## Recovery Unlike seed-phrase-based wallets where loss means permanent loss of funds, delegated wallets support recovery: | | Seed phrase (traditional) | API credential (Dfns) | | ------------- | ------------------------- | ------------------------- | | If lost | Funds lost forever | Can be re-established | | If stolen | Funds stolen | Can be revoked | | Backup method | Write down 24 words | Register multiple devices | ### Recovery strategies Your application should implement ways for end users to register additional credentials: * **Same device** - Users can add another passkey (e.g., a hardware security key) using their existing credential to sign the request. See how this works in the dashboard: [Registering a new passkey credential](/guides/registering-a-new-passkey-credential). * **New device** - Users can register a passkey on a different device using a time-limited registration code. See how this works in the dashboard: [Onboarding a new device](/guides/onboarding-a-new-device). * **Recovery credentials** - Users store a recovery password securely offline, which can be used to register a new passkey if all other credentials are lost. For implementation details and code examples, see [Implementing end-user recovery](/guides/developers/end-user-recovery). ## Trade-offs | Delegated wallets | Organization-managed wallets | | ---------------------------------------- | ---------------------------------- | | User has full control | Your team controls wallets | | No spending limits or approval workflows | Policies can restrict transactions | | User responsible for recovery | You can help users recover access | | Regulatory clarity on custody | You may be considered a custodian | ## When to use delegated wallets **Good fit:** * Consumer apps where users expect to own their assets * Regulatory environments where custody is a concern * Products where user trust and transparency matter **Consider org-managed instead:** * Treasury or operational wallets * Scenarios requiring spending limits or multi-approval * When users expect you to help if something goes wrong ## White-labeling Delegation allows you to provide Dfns wallet infrastructure without exposing Dfns to your users. Your backend registers and logs in users to Dfns on their behalf. Users only interact with your app and your brand - no Dfns emails, no Dfns branding. When users need to sign transactions, your app prompts them for their passkey directly. End users are first-class citizens in Dfns. Once registered, they could use the Dfns APIs directly if they access their auth token. Carefully review your policies and controls. ## Learn more * [End-user wallets solution](/solutions/end-user-wallets) - Implementation overview * [Wallet delegation guide](/guides/developers/wallet-delegation) - Step-by-step developer guide * [End-user authentication](/guides/developers/end-user-authentication) - Registration and login flows * [End-user recovery](/guides/developers/end-user-recovery) - Implementing recovery # Using Hardware Security Modules (HSMs) Source: https://docs.dfns.co/advanced/deployment-models/hsm Dfns provides robust support for integrating Hardware Security Modules (HSMs) to secure wallet keys, offering an alternative to the Multi-Party Computation (MPC) cluster. By leveraging an HSM, customers can choose an alternate key store to secure their cryptographic keys while maintaining full compatibility with existing Dfns APIs and capabilities. Once the HSM is deployed, no changes are required to the customer's integration; all APIs, workflows, and functionalities remain identical to those used with the MPC cluster. ## Architecture overview The HSM deployment model consists of four components running in your infrastructure: | Component | Description | | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **HSM** | A Hardware Security Module that you procure and manage. It performs cryptographic operations and protects your master key. Any HSM supporting PKCS#11 is compatible. | | **Host server** | The machine running the HSM Driver and database. It must have network connectivity to both the internet (to reach Dfns APIs) and your HSM. | | **HSM Driver** | Software provided by Dfns that bridges the Dfns API and your HSM. It polls the API for signing requests and translates them into PKCS#11 commands. | | **Database** | A database that stores wrapped (encrypted) keys. The HSM Driver reads and writes to this database during key generation and signing operations. | You are responsible for procuring, provisioning, and operating all of these components. Dfns provides the HSM Driver software and coordinates mTLS certificate setup, but does not have access to your infrastructure or keys. **Dfns does not participate in the administration or management of the customer’s HSM**. All HSM-related operations, including provisioning, configuration, and master key management, are handled exclusively by the customer. This ensures that Dfns personnel have no access to the cryptographic keys, aligning with strict security and compliance requirements. Customers are free to use an existing HSM or procure a new one, provided it supports the PKCS#11 standard. The stateless design and PKCS#11 compatibility eliminate the need for specific HSM models or configurations, offering maximum flexibility. For redundancy, you can deploy multiple HSMs and HSM Driver instances. See [Horizontal scaling and redundancy](#horizontal-scaling-and-redundancy) for details. ## HSM usage To maximize compatibility and flexibility, Dfns employs a stateless approach to HSM usage. This design eliminates the need for persistent key storage within the HSM, simplifying integration and enhancing disaster recovery capabilities. This also ensures that the HSM does not need to maintain key state, enabling compatibility with a broad range of HSMs and simplifying key management. ### Key generation ```mermaid theme={null} sequenceDiagram participant User participant API as Dfns APIs participant Driver as HSM Driver participant HSM participant DB as Database User->>API: Create wallet request Driver->>API: Poll for requests (mTLS) API-->>Driver: Key generation request Driver->>HSM: Generate key (PKCS#35;11) HSM-->>HSM: Generate key & wrap with master key HSM-->>Driver: Wrapped key Driver->>DB: Store wrapped key Driver->>API: Return public key API-->>User: Wallet created ``` The HSM Driver polls the Dfns APIs and retrieves a key generation request. It forwards the request to the HSM, which generates a new cryptographic key. The HSM wraps (encrypts) the key using its master key, producing a wrapped key. The HSM Driver retrieves the wrapped key and stores it in a secure database for backup and future use. ### Transaction signing ```mermaid theme={null} sequenceDiagram participant User participant API as Dfns APIs participant Driver as HSM Driver participant HSM participant DB as Database User->>API: Sign transaction request Driver->>API: Poll for requests (mTLS) API-->>Driver: Signing request + payload Driver->>DB: Retrieve wrapped key DB-->>Driver: Wrapped key Driver->>HSM: Wrapped key + payload (PKCS#35;11) HSM-->>HSM: Unwrap key & sign payload HSM-->>Driver: Signed payload Driver->>API: Return signature API-->>User: Transaction signed ``` The HSM Driver polls the Dfns APIs and retrieves a signing request, including the payload to be signed. It retrieves the corresponding wrapped key from the database. The HSM Driver sends the wrapped key and the payload to the HSM. The HSM unwraps (decrypts) the key using its master key, performs the signature operation, and returns the signed payload to the HSM Driver. The HSM Driver forwards the signed payload to the Dfns APIs for processing. ## HSM Driver The HSM Driver is a specialized component designed to facilitate secure integration between Dfns APIs and HSMs. It provides deep compatibility with the PKCS#11 standard, enabling seamless interaction with a wide range of HSM models from various vendors. The HSM Driver operates as a bridge, handling key generation and signing requests while ensuring state-of-the-art security and operational flexibility. The HSM Driver has two primary functionalities: 1. **Polling Dfns APIs**: The HSM Driver continuously polls the Dfns APIs to retrieve requests for generating new keys or signing transactions using existing keys. The connection between the HSM Driver and Dfns APIs is secured using mutual Transport Layer Security (mTLS) with strong authorization mechanisms, ensuring end-to-end encryption and authentication. 2. **Interfacing with HSMs via PKCS#11**: The HSM Driver translates API requests into PKCS#11 commands to interact with the HSM. This abstraction allows the HSM Driver to support diverse HSM models without requiring specific hardware configurations. ## Horizontal scaling and redundancy The HSM Driver and HSM integration are designed for horizontal scaling to support high availability and business continuity. Customers can deploy multiple HSMs and HSM Driver instances to handle increased load or ensure redundancy. The only requirements for scaling are: * All HSMs must be provisioned with the same master key to unwrap keys consistently. * All HSM Driver instances must have access to the same database containing the wrapped keys. This architecture allows customers to distribute workload across multiple HSMs, ensuring resilience and performance under varying operational demands. ### Active-active configuration Instead of relying on a single processing chain (one server, one HSM), the architecture supports multiple, independent HSM Drivers running in parallel. Each HSM Driver can be paired with its own HSM. All deployed HSM Drivers connect to the Dfns API simultaneously, independently polling for jobs. ### Queue-based load distribution The Dfns API maintains a queue of incoming requests. Each active HSM Driver connects to poll for the next available job. This pull-based model provides: * **Natural load distribution**: The next job is always taken by the next available server, distributing work across all healthy instances. * **Intrinsic fault tolerance**: If an HSM Driver or its paired HSM fails, it simply stops polling. The API and its request queue are unaffected. The remaining healthy HSM Drivers continue processing requests without any service interruption or need for manual failover. ### Automatic recovery When a failed HSM or HSM Driver is repaired and brought back online, it simply resumes connecting to the API and polling for available jobs. It is automatically re-integrated into the active processing pool without requiring any manual intervention or API-side configuration. ## Deployment options The HSM Driver is a flexible component that can be deployed on the customer’s infrastructure, offering multiple packaging and deployment options: * **Container Image**: The HSM Driver can be provided as a Docker container image, enabling easy deployment in containerized environments such as Kubernetes or Docker Swarm. * **Standalone Binary**: For environments without containerization, the HSM Driver is available as a standalone binary, compatible with common operating systems. * **Co-Located Deployment**: The HSM Driver can be run on the same machine as the HSM to minimize latency and enhance security by reducing network exposure. * **Cloud-Based HSM Support**: Customers can opt for cloud-based HSMs (e.g., AWS CloudHSM, Azure Key Vault HSM, Google Cloud HSM) if they prefer a managed HSM solution. ## Integration steps To integrate an HSM with Dfns, customers must perform the following steps: Contact Dfns to acquire the HSM Driver component, available as a container image or standalone binary. Sync with Dfns to configure mTLS certificates for secure communication between the HSM Driver and Dfns APIs. Ensure that the certificates are properly provisioned and validated. Install and configure the HSM Driver on the customer's infrastructure, ensuring connectivity to the HSM and the wrapped key database. If using a new HSM, configure the HSM with a master key and ensure it supports PKCS#11. If using multiple HSMs, provision them with the same master key. Start the HSM Driver, which will begin polling Dfns APIs and processing key generation and signing requests via the HSM. Once these steps are complete, the HSM integration is fully operational, and customers can continue using the same Dfns APIs as before, with no changes to their existing workflows. ## Backup and disaster recovery The wrapped keys stored in the database are encrypted with the HSM’s master key, ensuring that they remain secure even if the database is compromised. The database can be backed up and replicated across multiple locations, providing robust disaster recovery capabilities. In the event of an HSM failure, a new HSM provisioned with the same master key can access the wrapped keys from the database, allowing seamless recovery without key loss. The HSM and database are run in your infrastructure. You are responsible for maintaining them operational! The HSM master keys are highly sensitive and should be replicated or backed up accordingly. The keys database only contains wrapped keys, so if you loose the master key then you loose the ability to use all wallets! ## Security considerations * **mTLS Authentication**: The use of mTLS between the HSM Driver and Dfns APIs ensures that only authorized components can communicate, preventing unauthorized access. * **Wrapped Key Encryption**: Keys stored in the database are encrypted with the HSM’s master key, rendering them unusable without access to the HSM. * **Customer-Controlled HSM**: By managing the HSM independently, customers retain full control over their cryptographic keys, ensuring compliance with internal security policies. * **Stateless Design:** The stateless approach minimizes the attack surface on the HSM and simplifies key recovery in case of hardware failure. For further assistance or to obtain the HSM Driver component, please contact the Dfns support team at [https://support.dfns.co](https://support.dfns.co). # Dfns deployment models Source: https://docs.dfns.co/advanced/deployment-models/index At Dfns, we understand that security is not one-size-fits-all. Different organizations have unique requirements for control, compliance, and operational responsibility. That's why we offer several **deployment models** for your signing infrastructure. A deployment model simply defines **where your wallet's secret key shares are stored and operated**. It determines the balance of responsibility between Dfns and your organization, allowing you to choose the perfect setup for your security posture and business needs. We offer four primary deployment models, or a mix of them. Each provides the highest security level but varies in operational management and control. For your application integration, the Dfns API remains consistent across all deployment models. You can switch between models as your requirements evolve without changing your application code. ## Fully-managed MPC in Dfns Cloud This is the standard, default, and most popular option. In this model, Dfns securely manages all the key shares within our robust, geographically distributed cloud infrastructure. It's a turnkey solution that provides institutional-grade security with zero operational overhead for your team. * **You get:** Maximum convenience and the full security of the Dfns platform without managing any infrastructure. ## Hybrid MPC The Hybrid model offers a powerful balance of control and convenience. Dfns manages a portion of the key shares in our cloud, while your organization securely holds one or more shares within your own environment. This makes you a required participant in every signing ceremony, giving you a direct cryptographic veto over any transaction. In this model, you deploy and operate a Signing Server (provided by Dfns) within your infrastructure. This server securely stores your key share(s) and interfaces with Dfns during signing operations. * **You get:** Shared security responsibility and direct control over transaction finality. You can choose your preferred MPC threshold scheme (we recommend 3-out-of-5, but any configuration can be implemented) as well as how many signers are operated by Dfns versus your organization. ## On-Premise / Self-Hosted MPC For organizations with the strictest data residency, compliance, or infrastructure requirements, we offer a fully on-premise deployment. In this model, you run the Dfns signing software and manage all key shares entirely within your own data centers or private cloud. In this model, you are responsible for deploying, operating, and maintaining the entire signing infrastructure, including the Signing Server and key shares. Dfns provides the software and support, but all cryptographic operations occur within your controlled environment. * **You get:** Maximum control over your keys and infrastructure. You can choose your preferred MPC threshold scheme. We recommend 3-out-of-5, but any configuration can be implemented to match your security requirements. ## On-Premise HSM For organizations seeking to add a layer of physically-enforced, tamper-resistant security to your cryptographic operations, ensuring your key shares never leave the protected boundary of your hardware, **Hardware Security Modules (HSMs)** are the gold standard. Dfns supports integrating customer-owned HSMs. In this model, you deploy the HSMs and an HSM Driver that interfaces with your HSM using the PKCS#11 standard. The HSM Driver handles communication between Dfns and the HSM, ensuring that keys are securely managed and signing operations are performed within the HSM's protected environment. * **You get:** Key security with hardware-enforced protections and full control over your cryptographic environment. ## Choosing the Right Model for You The best model depends on your specific needs for control versus convenience. The table below outlines the key differences to help you decide. | Feature | Dfns Cloud (Fully-Managed) | Hybrid Cloud | On-Premise (Self-Hosted) | | :-------------------- | :----------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------ | | **Key Share Custody** | All shares secured and stored by Dfns | Shared (Dfns & Customer) | All shares held by Customer | | **HSM Support** | No | No | Yes | | **Primary Benefit** | Simplicity & Speed | Shared Control & Veto Power | Maximum Control & Data Residency | | **Best For** | Most startups, fintechs, and enterprises that want to move fast without managing infrastructure. | Institutions that require a cryptographic role in transaction signing for compliance or internal policy. | Financial institutions or government entities with strict data locality rules or dedicated internal security teams. | ## More information To learn more about the technical architecture and operational requirements of each model, please explore the detailed guides: * [Detailed Guide: On-Premise Deployment](/advanced/deployment-models/on-premise-deployment) * [Detailed Guide: Using HSMs](/advanced/deployment-models/hsm) # On premise deployment Source: https://docs.dfns.co/advanced/deployment-models/on-premise-deployment With Dfns you can deploy the signers or the HSM Driver on your infrastructure. With Dfns, you can deploy key management infrastructure on your own premises. This gives you direct control over your cryptographic operations while still benefiting from the Dfns API and platform capabilities. On-premise deployments require your team to manage the underlying infrastructure. This includes operating the signers or HSM, networking, software updates, backups, and disaster recovery. Ensure you have the operational capacity before choosing this model. ## Deployment options ### Hybrid MPC In the Hybrid model, Dfns manages some MPC signers in our cloud while you operate one or more signers in your own infrastructure. This makes you a required participant in every signing ceremony. You can choose your preferred MPC threshold scheme (we recommend 3-out-of-5, but any configuration can be implemented) as well as how many signers are operated by Dfns versus your organization. ### On-premise MPC In the fully on-premise MPC model, you manage all MPC signers within your own data centers or private cloud. The Dfns API coordinates the signing ceremonies, but all key shares remain under your control. You can choose your preferred MPC threshold scheme. We recommend 3-out-of-5, but any configuration can be implemented to match your security requirements. ### HSM integration As an alternative to MPC, you can use a Hardware Security Module (HSM) to secure your wallet keys. The HSM Driver polls the Dfns API and interfaces with your HSM via PKCS#11. For detailed information about HSM integration, see [Using Hardware Security Modules (HSMs)](/advanced/deployment-models/hsm). ## Getting started Interested in deploying Dfns infrastructure on your premises? Please contact the Dfns support team at [https://support.dfns.co](https://support.dfns.co). # Governance architecture Source: https://docs.dfns.co/advanced/governance-architecture How authentication, policies, and MPC signing work together This page explains how Dfns' governance layers work together to secure your digital assets. ## Overview Every Dfns API request passes through multiple security layers before a blockchain transaction is signed: ```mermaid theme={null} flowchart TB App[Your Application] subgraph Auth[1: Authentication] AuthCheck["Verify API token
Verify user action signature"] end subgraph Authz[2: Authorization] PermCheck["Check user permissions
e.g., Wallets:Sign"] end subgraph Policy[3: Policy Engine] PolicyEval["Evaluate matching policies"] end Blocked([Blocked]) ApprovalRequired["Approval Required"] HumanApproval{"Human Review"} Rejected([Rejected]) Approved["Approved"] subgraph MPC[4: MPC Signing] MPCSign["Distributed key shares
sign collaboratively"] end subgraph Broadcast[5: Broadcast] BroadcastTx["Send to blockchain"] end App --> Auth Auth --> Authz Authz --> Policy Policy --> Blocked Policy --> ApprovalRequired Policy --> MPC ApprovalRequired --> HumanApproval HumanApproval -->|Reject| Rejected HumanApproval -->|Approve| Approved Approved --> MPC MPC --> Broadcast ``` ## Layer 1: Authentication Every API request must prove identity through two mechanisms: ### API Token The `Authorization: Bearer ` header identifies who is making the request: * **User tokens**: Short-lived, obtained through login flow * **Service account tokens**: Long-lived, for server-to-server communication * **Personal access tokens**: Long-lived user tokens for development ### User Action Signature For state-changing operations (POST, PUT, DELETE), the `X-DFNS-USERACTION` header proves the caller controls a registered credential: 1. Client requests a challenge from Dfns 2. Client signs the challenge with their credential (passkey or asymmetric key) 3. 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. ## Layer 2: Authorization (Permissions) 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: ```mermaid theme={null} flowchart LR User --> Permission --> Operations ``` Example: A user with `Wallets:Read` can view wallets but cannot transfer assets (requires `Wallets:Sign`). See [Permissions](/core-concepts/roles-and-permissions) for the full list. ## Layer 3: Policy Engine Even with valid authentication and permissions, the Policy Engine can add additional controls: | Policy action | Effect | | ----------------- | -------------------------------------------------------- | | `Block` | Transaction is rejected | | `RequestApproval` | Transaction held until humans approve | | `NoAction` | Transaction proceeds (used with Chainalysis for logging) | Policies evaluate rules like: * Transaction amount limits * Velocity limits (amount or count over time) * Recipient whitelisting * Chainalysis screening **Important:** All matching policies are evaluated for every activity. If multiple policies apply: * Any `Block` result immediately blocks the activity * Multiple `RequestApproval` results require approvals from all triggered policies * Policies cannot bypass or override each other See [Policies](/core-concepts/policies) for details. ## Layer 4: MPC Signing Once a transaction passes all checks, the MPC signing ceremony begins: ```mermaid theme={null} flowchart TB subgraph MPC["Dfns MPC Network"] direction TB subgraph Signers[" "] direction LR S1["Signer Node
Share 1"] S2["Signer Node
Share 2"] S3["Signer Node
Share 3"] S4["Signer Node
Share 4"] end Threshold["Threshold Signature
(k-of-n nodes collaborate)"] S1 --> Threshold S2 --> Threshold S3 --> Threshold S4 --> Threshold end ``` Key properties: * **No complete key**: The private key never exists in one place * **Threshold security**: Requires k-of-n shares to sign (not all shares needed) * **Geographic distribution**: Nodes are in different data centers/regions * **Audit trail**: Every signing ceremony is logged ## Layer 5: Broadcast The signed transaction is broadcast to the blockchain network. Dfns monitors for confirmation and updates transaction status. ## Security model summary | Layer | What it protects against | | ------------------- | ------------------------------------- | | Authentication | Unauthorized access | | User action signing | Token theft, replay attacks | | Permissions | Privilege escalation | | Policies | Unauthorized transactions, fraud | | MPC | Key theft, single point of compromise | ## Separation of concerns A critical security property: **credentials and keys are completely separate**. | Credential (Authentication) | Key (Signing) | | ----------------------------------------------------------- | ----------------------------- | | Proves identity | Signs transactions | | Stored on user device (passkey) or server (service account) | Stored in MPC network | | Can be revoked/rotated | Key shares are immutable | | Compromised credential ≠ stolen assets | Protected by all layers above | Even if an attacker steals credentials, they still face: * User action signing requirements * Permission checks * Policy enforcement * MPC threshold requirements ## Related Deep dive into MPC technology Configuring transaction policies Understanding permission model Authentication flows # Key import and export Source: https://docs.dfns.co/advanced/importing-existing-keys Import existing private keys into Dfns or export keys from Dfns. Dfns secures private keys by generating them as MPC key shares in our decentralized key management network. This happens by default when you [create a wallet](/api-reference/wallets/create-wallet). In some circumstances, you may need to import an existing private key or export a key from Dfns. These features are restricted to Enterprise customers. ## Import **We recommend creating new wallets and transferring funds instead of importing keys.** Imported keys are inherently less secure because they existed in complete form before import. You cannot verify how the key was stored, handled, or who may have had access to it. Keys generated natively by Dfns MPC have never existed as a complete key and provide stronger security guarantees. Dfns uses MPC (Multi-Party Computation) to secure keys. When you import a key, the SDK processes it entirely on your machine using WebAssembly: 1. **Fetch signers** - The SDK retrieves Dfns signer nodes and their public keys 2. **Split locally** - Your private key is split into shares using threshold cryptography 3. **Encrypt for signers** - Each share is encrypted with the corresponding signer's public key 4. **Transmit shares** - Only encrypted shares are sent to Dfns The complete private key never leaves your machine and never exists on Dfns servers. Once imported, the key operates like any Dfns-native key with full MPC security for signing operations. For detailed import instructions including vendor-specific migration steps, see the developer guide. ### After importing a key Once you've imported a key, you can: * **Create wallets from it**: Use [Create Wallet](/api-reference/wallets/create-wallet) with `signingKey.id` to create wallets on specific networks * **Sign directly**: Use the [Signing API](/api-reference/sign) for raw signatures * **Multi-chain usage**: The same key can be used across compatible networks (e.g., all EVM chains share the same address) ### When to import vs create new **Import makes sense when:** * The wallet address is tied to a smart contract you can't redeploy * You have regulatory requirements to maintain specific addresses * The address has non-transferable assets (certain NFTs, protocol permissions) **Create new keys instead when:** * Starting fresh with no legacy requirements * High-value production wallets * You can move assets from old wallets ## Export Export a key from Dfns to use it outside the platform. Dfns cannot guarantee the security of transactions signed with exported keys. This feature requires a contractual addendum. See the [export SDK example](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/sdk/export-wallet) for implementation details. ## Related Understanding the difference between keys and wallets Import SDK implementation examples # Agreements Source: https://docs.dfns.co/api-reference/agreements Sign Dfns and third-party providers service agreements, privacy policy, etc Some Dfns services require an explicit agreement acceptance before they can be used. The agreements API allows you to programmatically view and sign these agreements ### Supported Agreements The list below shows which agreements types are available on the API. | Agreement Type | Description | | --------------------- | -------------------------------------------------------------------------------------- | | UniswapTermsOfService | The terms of service to use the UniswapClassic and UniswapX providers on the Swaps API | | UniswapPrivacyPolicy | The privacy policy to use the UniswapClassic and UniswapX providers on the Swaps API | # Get Latest Unaccepted Agreement Source: https://docs.dfns.co/api-reference/agreements/get-latest-unaccepted-agreement openapi.yaml get /agreements/latest-unaccepted Get the latest unaccepted agreement for a specific agreement type #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions `Agreements:Acceptance:Read`: Always required. # Record Agreement Acceptance Source: https://docs.dfns.co/api-reference/agreements/record-agreement-acceptance openapi.yaml post /agreements/{agreementId}/accept Record the acceptance of a specific agreement by its ID #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions `Agreements:Acceptance:Create`: Always required. # Allocations Source: https://docs.dfns.co/api-reference/allocations Dfns supports reward generation via multiple providers to let you earn rewards on your crypto holdings across supported chains. Below is an overview of the rewards providers, what they are, and which chains each supports. ## Providers | Provider | Description | Supported Chains | | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------- | | 0fns | The first allocation protocol available in Dfns Allocations. It is an extension to the M0 USD-based stablecoin \$M that offers rewards to holders. With 0fns you can trade your USDC on Ethereum into 0fns and begin earning rewards right away. | Ethereum Mainnet, Ethereum Sepolia | ## Flow Overview 1. **Create an Allocation position**: Create a new allocation position by depositing/trading assets into the Allocations protocol. 2. **Track Status**: Monitor the Allocation position execution. 3. **Increase/Decrease position**: Add or remove assets from an existing Allocation position. ## Allocation object # Create Allocation Source: https://docs.dfns.co/api-reference/allocations/create-allocation openapi.yaml post /allocations Create a new allocation. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions `Allocations:Create`: Always required. # Create Allocation Action Source: https://docs.dfns.co/api-reference/allocations/create-allocation-action openapi.yaml post /allocations/{allocationId}/actions Create a new action for an existing allocation. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions `Allocations:Update`: Always required. # Get Allocation Source: https://docs.dfns.co/api-reference/allocations/get-allocation openapi.yaml get /allocations/{allocationId} Retrieve the details of a specific allocation. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions `Allocations:Read`: Always required. # List Allocation Actions Source: https://docs.dfns.co/api-reference/allocations/list-allocation-actions openapi.yaml get /allocations/{allocationId}/actions Retrieve the list of actions for a specific allocation. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions `Allocations:Read`: Always required. # List Allocations Source: https://docs.dfns.co/api-reference/allocations/list-allocations openapi.yaml get /allocations #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions `Allocations:Read`: Always required. # Account recovery Source: https://docs.dfns.co/api-reference/auth/account-recovery Users can recover their Dfns accounts using recovery credentials. When a recovery credential is used, all existing credentials (both regular and recovery) are invalidated for security. The user must create new credentials during the recovery process. ## Guides Step-by-step guide for employees to recover their account using the dashboard. Developer guide for implementing recovery flows for delegated wallet users. ## Related endpoints * /auth/recover/init – [Create recovery challenge](/api-reference/auth/create-recovery-challenge) * /auth/recover/user/delegated – [Create delegated recovery challenge](/api-reference/auth/create-delegated-recovery-challenge) * /auth/recover/user – [Recover user](/api-reference/auth/recover-user) # Activate Credential Source: https://docs.dfns.co/api-reference/auth/activate-credential openapi.yaml put /auth/credentials/activate Activates a credential that was previously deactivated. If the credential is already activated no action is taken. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ✅ Delegated User (`EndUser`)\ ❌ Personal Access Token not allowed\ ❌ Service Account #### Required Permissions No permission required. # Activate Personal Access Token Source: https://docs.dfns.co/api-reference/auth/activate-personal-access-token openapi.yaml put /auth/pats/{tokenId}/activate Activate a specific Personal Access Token. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ✅ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions No permission required. # Activate Service Account Source: https://docs.dfns.co/api-reference/auth/activate-service-account openapi.yaml put /auth/service-accounts/{serviceAccountId}/activate Activate a specific Service Account. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ❌ Personal Access Token not allowed\ ✅ Service Account #### Required Permissions `Auth:ServiceAccounts:Activate`: Always required. # Activate User Source: https://docs.dfns.co/api-reference/auth/activate-user openapi.yaml put /auth/users/{userId}/activate Activate a specific User. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ❌ Personal Access Token not allowed\ ✅ Service Account #### Required Permissions `Auth:Users:Activate`: Always required. # Complete End User Registration with Wallets Source: https://docs.dfns.co/api-reference/auth/complete-end-user-registration-with-wallets openapi.yaml post /auth/registration/enduser Completes the end user registration process and creates the user's initial credentials along with delegated wallets for the new end user. The type of credentials being registered is determined by the `credentialKind` field in the nested objects (`firstFactorCredential` , `secondFactorCredential` and `RecoveryCredential`). Supported credential kinds are: * `Fido2`: User action is signed by a user's signing device using `WebAuthn`. * `Key`: User action is signed by a user's, or token's, private key. * `PasswordProtectedKey`: User action is signed by a user's, or token's, private key. The encrypted version of the private key is stored by Dfns and returns during the signing flow for the user to decrypt it. The number of delegated wallets created and the wallet types are determined by the `wallets` specifications. The end user is automatically assigned `ManagedDefaultEndUserAccess` managed permission that grants the end user full access to the wallets. #### Authentication ❌ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ❌ Service Account\ ✅ Registration Code #### Required Permissions No permission required. # Complete SSO Login Source: https://docs.dfns.co/api-reference/auth/complete-sso-login openapi.yaml post /auth/login/sso Completes the login process and provides the authenticated user with their authentication token. #### Authentication No authentication required. #### Required Permissions No authentication required. # Complete User Login Source: https://docs.dfns.co/api-reference/auth/complete-user-login openapi.yaml post /auth/login Completes the login process and provides the authenticated user with their authentication token. The type of credentials used to login is determined by the `kind` field in the nested objects (`firstFactor` and `secondFactor`). Supported credential kinds are: * `Fido2`: Login challenge is signed by a user's signing device using `WebAuthn`. * `Key`: Login challenge is signed by a user's private key. * `PasswordProtectedKey`: Login challenge is signed by the decrypted user's private key that was sent during [Create User Login Challenge](../registration/inituserregistration) step. #### Authentication No authentication required. #### Required Permissions No authentication required. # Complete User Registration Source: https://docs.dfns.co/api-reference/auth/complete-user-registration openapi.yaml post /auth/registration Completes the user registration process and creates the user's initial credentials. The type of credentials being registered is determined by the `credentialKind` field in the nested objects (`firstFactorCredential` , `secondFactorCredential` and `RecoveryCredential`). Supported credential kinds are: * `Fido2`: User action is signed by a user's signing device using `WebAuthn`. * `Key`: User action is signed by a user's, or token's, private key. * `PasswordProtectedKey`: User action is signed by a user's, or token's, private key. The encrypted version of the private key is stored by Dfns and returns during the signing flow for the user to decrypt it. * `RecoveryKey` : Similar to `PasswordProtectedKey`, but this credential can only be used to recover an account not to sign an action or login. Once this credential is used all the other user's credentials are invalidated. #### Authentication ❌ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ❌ Service Account\ ✅ Registration Code #### Required Permissions No permission required. # Create Credential Source: https://docs.dfns.co/api-reference/auth/create-credential openapi.yaml post /auth/credentials Part of the flow [Create Credential Regular flow](https://docs.dfns.co/api-reference/auth/credentials#regular-flow). Adds a new credential to a user's account. See [Credential Kinds](https://docs.dfns.co/api-reference/auth/credentials#credential-kinds) for all supported credential types. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ✅ Delegated User (`EndUser`)\ ❌ Personal Access Token not allowed\ ❌ Service Account #### Required Permissions No permission required. # Create Credential Challenge Source: https://docs.dfns.co/api-reference/auth/create-credential-challenge openapi.yaml post /auth/credentials/init Part of the flow [Create Credential Regular flow](https://docs.dfns.co/api-reference/auth/credentials#regular-flow). Starts a create user credential session, returning a challenge that will be used to verify the user's identity. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ✅ Delegated User (`EndUser`)\ ❌ Personal Access Token not allowed\ ❌ Service Account #### Required Permissions No permission required. # Create Credential Challenge With Code Source: https://docs.dfns.co/api-reference/auth/create-credential-challenge-with-code openapi.yaml post /auth/credentials/code/init Part of the flow [Create Credential With Code](https://docs.dfns.co/api-reference/auth/credentials#create-credential-with-code-flow). Creates a credential challenge using a one time code-time-code. This challenge must then be signed by the new credential, before finalizing the flow. #### Authentication No authentication required. #### Required Permissions No authentication required. # Create Credential Code Source: https://docs.dfns.co/api-reference/auth/create-credential-code openapi.yaml post /auth/credentials/code Part of the [Create Credential With Code flow](https://docs.dfns.co/api-reference/auth/credentials#create-credential-with-code-flow). Creates a one-time-code that can then be used to create a new credential from a place you don't have access to one of your existing credential. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ✅ Delegated User (`EndUser`)\ ❌ Personal Access Token not allowed\ ❌ Service Account #### Required Permissions No permission required. # Create Credential With Code Source: https://docs.dfns.co/api-reference/auth/create-credential-with-code openapi.yaml post /auth/credentials/code/verify Finalizes the flow [Create Credential With Code](https://docs.dfns.co/api-reference/auth/credentials#create-credential-with-code-flow). Adds a new credential to a user's account. This endpoint is similar to the [Create Credential](https://docs.dfns.co/api-reference/auth/create-credential) endpoint, except: * it does not need the user to be authenticated * it does not need user action signing * it will only work with the challenge gotten from the [Create Credential Challenge With Code](https://docs.dfns.co/api-reference/auth/create-credential-challenge-with-code) endpoint #### Authentication No authentication required. #### Required Permissions No authentication required. # Create Delegated Recovery Challenge Source: https://docs.dfns.co/api-reference/auth/create-delegated-recovery-challenge openapi.yaml post /auth/recover/user/delegated Only a [Service Account](https://docs.dfns.co/api-reference/auth/service-accounts) can use this endpoint. This endpoint enables setting up a recovery workflow for Delegated Signing. Via this configuration, the end user will not receive an email from Dfns but instead can establish recovery credentials that leverage the customer's brand for the recovery workflow. Once the user has been verified by your auth system and this API has been called, you can call [Recover User](https://docs.dfns.co/api-reference/auth/recover-user) to complete the recovery process. #### Authentication ❌ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions `Auth:Recover:Delegated`: Always required. # Create Delegated Registration Challenge Source: https://docs.dfns.co/api-reference/auth/create-delegated-registration-challenge openapi.yaml post /auth/registration/delegated Only a [Service Account](https://docs.dfns.co/api-reference/auth/service-accounts) can use this endpoint. If you want to use your own authentication system, while still using `Delegated Signing`, you can use this endpoint to register a new End User in your organization, without your user needing to receive an email from Dfns. This endpoint will: 1. Create a new User attached to your organization 2. Initiates a User Registration Challenge and returns the registration challenge. On successful creation, the user's registration challenge will be returned. You will then need to call [Complete User Registration](https://docs.dfns.co/api-reference/auth/complete-user-registration) or [Complete End User Registration with Wallets](https://docs.dfns.co/api-reference/auth/complete-end-user-registration-with-wallets) to complete the user's registration. #### Authentication ❌ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions `Auth:Register:Delegated`: Always required. # Create Login Challenge Source: https://docs.dfns.co/api-reference/auth/create-login-challenge openapi.yaml post /auth/login/init Start a user login session, returning a challenge that will be used to verify the user's identity. If the user has a credential of kind `PasswordProtectedKey` a temporary one time code needs to be passed in the `loginCode` field. If the user has at least one discoverable WebAuthn credential, `username` is optional (username-less flow). #### Authentication No authentication required. #### Required Permissions No authentication required. # Create Personal Access Token Source: https://docs.dfns.co/api-reference/auth/create-personal-access-token openapi.yaml post /auth/pats Create a new Personal Access Token for the caller. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ✅ Delegated User (`EndUser`)\ ❌ Personal Access Token not allowed\ ❌ Service Account #### Required Permissions `Auth:Pats:Create`: Always required. # Create Recovery Challenge Source: https://docs.dfns.co/api-reference/auth/create-recovery-challenge openapi.yaml post /auth/recover/user/init Starts a user recovery session, returning a challenge that will be used to verify the user's identity. #### Authentication No authentication required. #### Required Permissions No authentication required. # Create Registration Challenge Source: https://docs.dfns.co/api-reference/auth/create-registration-challenge openapi.yaml post /auth/registration/init Starts a user registration session. It returns a challenge that will need to be signed by a passkey and used to perform the step [Complete User Registration](/api-reference/auth/register) #### Authentication No authentication required. #### Required Permissions No authentication required. # Create Service Account Source: https://docs.dfns.co/api-reference/auth/create-service-account openapi.yaml post /auth/service-accounts Create a new Service Account for your organization. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ❌ Personal Access Token not allowed\ ❌ Service Account #### Required Permissions `Auth:ServiceAccounts:Create`: Always required. # Create Social Registration Challenge Source: https://docs.dfns.co/api-reference/auth/create-social-registration-challenge openapi.yaml post /auth/registration/social Starts an end-user registration session by passing a JWT obtained by an IdP. It returns a challenge that will need to be signed by a passkey and used to perform [Complete End User Registration with Wallets](/api-reference/auth/register-end-user). #### Authentication No authentication required. #### Required Permissions No authentication required. # Create User Source: https://docs.dfns.co/api-reference/auth/create-user openapi.yaml post /auth/users Invite a new user in the caller's org. This will create the user and send a registration email to the created User's email, with a registration code, and pointing him to complete his registration on Dfns Dashboard. The user is created without any permissions. If you want the created User to not know about about Dfns, and don't want him to receive the registration email from Dfns, you should rather use the Delegated Registration endpoint. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ❌ Delegated User (`EndUser`)\ ❌ Personal Access Token not allowed\ ✅ Service Account #### Required Permissions `Auth:Users:Create`: Always required. # Create User Action Challenge Source: https://docs.dfns.co/api-reference/auth/create-user-action-challenge openapi.yaml post /auth/action/init Starts a user action signing session, returning a challenge that will be used to verify the user's intent to perform an action. This is the first step of the [User Action Signing flow](http://docs.dfns.co/api-reference/auth/signing-flows). #### Authentication ✅ Organization User (`CustomerEmployee`)\ ✅ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions No permission required. # Create User Action Signature Source: https://docs.dfns.co/api-reference/auth/create-user-action-signature openapi.yaml post /auth/action Completes the user action signing process and provides a signing token that can be used to verify the user intended to perform the action. This is the first step of the [User Action Signing flow](http://docs.dfns.co/api-reference/auth/signing-flows). The type of credentials used to sign the action is determined by the `kind` field in the nested objects (`firstFactor` and `secondFactor`). Supported credential kinds are: * `Fido2`: User action is signed by a user's signing device using `WebAuthn`. * `Key`: User action is signed by a user's, or token's, private key. * `PasswordProtectedKey`: Login challenge is signed by the decrypted user's private key that was sent during [Create User Action Signature Challenge](https://docs.dfns.co/api-reference/auth/create-user-action-challenge) step. #### Authentication ✅ Organization User (`CustomerEmployee`)\ ✅ Delegated User (`EndUser`)\ ✅ Service Account #### Required Permissions No permission required. # Credentials Source: https://docs.dfns.co/api-reference/auth/credentials User Credentials are used to sign any API call that requires user signature. Most API requests (non-readonly requests mostly) require such a signature. Credentials can be of different kinds (see below), but are essentially all a public/private keypair. The private part is only known and kept by the user. The public key is shared with Dfns, so Dfns can validate the signature produced by the private key. ## Credential Kinds The different Credential kinds are: * **`Fido2` Credential** (also known as "Passkeys" or "WebauthN credential"). This type of credential is the recommended one for any human user. It's relies on the [WebauthN standard](https://en.wikipedia.org/wiki/WebAuthn). Most recent devices (laptop, phones, browsers, password managers etc...) support passkeys nowadays. Your device will handle creating a passkey and storing it securely so the user can re-use it later on this same device. Passkeys are tied to a domain name, And you will need to whitelist this domain on Dfns dashboard first (by default, in your organisation, `localhost` is a whitelisted passkey domain, as well as `app.dfns.io`, so you can use your passkey on Dfns dashboard). * **`Key` Credential**. This is a "raw" public/private keypair, mostly meant to be used by [Service Accounts](/api-reference/auth/service-accounts) (aka "machine Users"). You are responsible for storing it securely, so that for example your Service Account can perform some API actions from your server. See [Generate a Key Pair](/guides/developers/generate-a-key-pair). * **`PasswordProtectedKey` Credential.** This is like a Key Credential expect that the private key is kept by Dfns in an encrypted way. Dfns does not have access to the password to decrypt it, only the customer or the end user does. You are responsible for implementing the routine to encrypt and decrypt the key (this should be done on the frontend side for delegated wallet so that you never have access to the decrypted private key). With this kind of credential you will send to Dfns an `encryptedPrivateKey` string during the registration containing the encrypted version of the private key. During the login and action signing flow the API will return this field that you will be able to decrypt to have access to the private key and perform the required signature. * **`RecoveryKey` Credential**. This is essentially like a Key Credential, but wrapped in a way where the User can just safekeep an intelligible human-readable recovery code. Users can print it and store it securely, or save this recovery code in some password manager, etc... ## Redundancy A User can create many Credentials, and that's even recommended, in case he loses one of his credential (eg. he loses his phone where was stored his passkey credential). They can create several passkeys credential on different devices (eg. one on his laptop, one on his phone, one in his password manager, on a yubikey etc...) ## Credential Signature Flow Most API requests (non-readonly requests mostly) require the signature from a valid Credential owned by the User. The credential signature flow usually looks like: 1. User calls a first endpoint to get a challenge back (some cypher text that needs to be signed) 2. User sign the challenge using a valid credential 3. User calls a second endpoint to submit the signature Different types of challenges that can be requested by a User: * A Registration Challenge (to register the first user credential, when user registers) * A Login Challenge (to login and get an auth token) * A User Action Challenge (required by most non-readonly API calls) * A Credential Challenge (used to create a new Credential) ## Credential Creation Flows There are two possible flows to create a new Credential for a User. The flow you will choose depend on where the User is (which app), and whether he has access access to his existing credential from this place. ### Regular flow This flow requires the last call (registration of the new credential) to be signed by an existing valid credential. That means that the user needs to have an existing credential accessible from the place where he's adding a new credential. 1. Call [Create Credential Challenge](/api-reference/auth/create-credential-challenge) to get a "Credential challenge" back. This endpoint does not require a user-action-signature required, so no credential signature involved here. 2. Create a new credential locally, sign the above challenge with it. 3. Call [Create Credential](/api-reference/auth/create-credential) to complete. This endpoint requires a [User Action Flow](/api-reference/auth/signing-flows), so it involves signing first **with an existing valid credential** to get an user action token. ### Create Credential With Code flow This flow requires the first call to be signed by an existing valid credential (creating the code). From then, the last steps can be performed without signature from a valid credential. This flow is useful when you want a user to create a new Credential from an app which doesn't have access to the existing valid credential (since passkeys are tied to the domain name, they cannot be used "cross-domain", eg. a passkey registered on domain `www.app-1.com` cannot be used inside the app `www.app-2.com)` 1. In App 1, call [Create Credential Code](/api-reference/auth/create-credential) to get a one-time code. The code will only be valid for 1 minute. This endpoint requires a [User Action Flow](/api-reference/auth/signing-flows), so it involves signing first **with an existing valid credential** to get an user action token. 2. In App 2, call [Create Credential Challenge With Code](/api-reference/auth/create-credential-challenge-with-code) (passing the code from step 1) to get a "Credential challenge" back 3. In App 2, create a new credential locally, sign the above challenge with it. 4. In App 2, call [Create Credential With Code](/api-reference/auth/create-credential-with-code) to complete (passing the code from step 1). This endpoint does not require a user-action-signature required, so no credential signature involved here This [demo video](https://www.loom.com/share/a8b3cbca4b934f659e2e37e676762b87?sid=6aa89bfa-ac59-4c87-897e-79085d916aa0) showcases this flow and how you could implement it in your product.