# 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 a [Gasless SDK for EOA wallets](https://docs-gasless.biconomy.io/) to enable sponsored transactions. They have [detailed documentation](https://docs-gasless.biconomy.io/products/enable-gasless-transactions/choose-an-approach-to-enable-gasless/eip-2771) on implementing the 2771 standard as well as funding deposits via their [Gas Tank](https://docs-gasless.biconomy.io/guides/gas-tank-deposits). They also cover the steps required to [enable a smart contract for 2771 support](https://docs-gasless.biconomy.io/tutorials/native-meta-transactions/enable-native-meta-transactions). Feel free to [reach out to the Biconomy team](https://docs-gasless.biconomy.io/comm/contact-us) 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](/developers/guides/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](/developers/guides/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 cyrpto 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 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 } ``` ### 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 theme={null} recoveryClientData = { type: 'key.get', challenge: base64url(JSON.stringify({ "firstFactorCredential":{ "credentialKind":"Key", "credentialInfo":{ "credId":"6Ca6tAOFTx2odyJBnCoRO-gPvfpfy0EOoOcEaxfxIOk", "clientData":"eyJ0eXBlIjoia2V5LmNyZWF0ZSIsImNoYWxsZW5nZSI6Ik1XTTBNbVk1WVRRME1EUmlOemRoTlRGaE56WTVPRFF3TldJNVpUUTRZMlJoT0RaaU5EazNaVFl6T1RFNU9HWXlNRGN4WmpCall6azRNbVE1WXpZMU1BIiwib3JpZ2luIjoiaHR0cHM6Ly9hcHAuZGZucy5uaW5qYSIsImNyb3NzT3JpZ2luIjpmYWxzZX0", "attestationData":"eyJwdWJsaWNLZXkiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTljRzJtRTREV0hid3dsTFJTS0JMWjltNitRc0NcbmVPcVdKaDF4NVZ2UkhaTWFQTFFsUnJoaGdiSG04dW5hNGg4UytMNW84c1Y4SHZ1amJsM01yQVRqM1E9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iLCJzaWduYXR1cmUiOiIzMDQ2MDIyMTAwOGUwMTA5ODQ4YzZmYzgzMDA0ZDBlNmM3ZmRhYzcxZGFlODUyNGZjNWEyOTA4MWQwMTJmODY1NDE2OTg2Y2UyOTAyMjEwMGY0N2UxYmVlNmM1MTc1YzQ0ODhiMTQzYzkzNmM2OGZhYzFhZTdlNzkzMWU3NmM2NzdkNDYzMzFlZDE0OWQxN2QifQ" } }, "recoveryCredential":{ "credentialKind":"RecoveryKey", "credentialInfo":{ "credId":"GMkW0zlmcoMxI1OX0Z96LL_Mz7dgeu6vOH5_TOeGyNk", "clientData":"eyJ0eXBlIjoia2V5LmNyZWF0ZSIsImNoYWxsZW5nZSI6Ik1XTTBNbVk1WVRRME1EUmlOemRoTlRGaE56WTVPRFF3TldJNVpUUTRZMlJoT0RaaU5EazNaVFl6T1RFNU9HWXlNRGN4WmpCall6azRNbVE1WXpZMU1BIiwib3JpZ2luIjoiaHR0cHM6Ly9hcHAuZGZucy5uaW5qYSIsImNyb3NzT3JpZ2luIjpmYWxzZX0", "attestationData":"eyJwdWJsaWNLZXkiOiItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFOWNHMm1FNERXSGJ3d2xMUlNLQkxaOW02K1FzQ1xuZU9xV0poMXg1VnZSSFpNYVBMUWxScmhoZ2JIbTh1bmE0aDhTK0w1bzhzVjhIdnVqYmwzTXJBVGozUT09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIsInNpZ25hdHVyZSI6IjMwNDYwMjIxMDBiZjBjZGU3ZGIyODQ0ZDhmOTIyZWQyOTNmN2E4NTVjM2U1Y2YzMjUxZjFhY2Q3M2I4MjNiNWZiOTIzZDNiY2FiMDIyMTAwY2YxM2U2ZDliY2ZiMjc3M2Q5ZDkyMDU4M2YwMWE0ODAyYmI4OTg5Y2NmZjMzNjJkYzJmN2U1ZjRmMTQzZjA2ZiJ9" }, "encryptedPrivateKey":"LsXVskHYqqrKKxBC9KvqStLEmxak5Y7NaboDDlRSIW7evUJpQTT1AYvx0EsFskmriaVb3AjTCGEv7gqUKokml1USL7+dVmrUVhV+cNWtS5AorvRuZr1FMGVKFkW1pKJhFNH2e2O661UhpyXsRXzcmksA7ZN/V37ZK7ITue0gs6I=" } })), origin: this.appOrigin, crossOrigin: false, } const clientData = Buffer.from(JSON.stringify(recoveryClientData)) const signature = crypto.sign(undefined, clientData, newKey.privateKey) ``` # Delegated Signing Source: https://docs.dfns.co/advanced/delegated-signing ### What is Delegated Signing? Delegated Signing is an innovative approach to non-custodial wallet deployments leveraging Dfns' industry-leading authentication to create seamless user experiences enabled by familiar technologies [like biometrics](https://www.coindesk.com/tech/2023/05/09/crypto-security-firm-dfns-adds-biometric-support-to-wallet-development-toolkit/). The goal of Delegated Signing is to optimize both user experience and security to onboard the next billion users to web3. As we have engaged with market segments such as DeFi, tokenization, and payments, we have seen significant demand for a solution which can delegate custodial responsibility to the end-user while preserving a seamless, Web2-like onboarding experience to ensure high conversion rates. In response, we have designed a configuration we call Delegated Signing, which gives end-users all the benefits of a self-custodial wallet like Metamask without forcing them to securely persist a 24-word seed phrase (or any other mnemonic secret). This page describes the architecture behind our Delegated Signing solution, how custody is delegated via an API signing secret, and how wallets can be recovered in the case of lost devices. ### Delegated Signing Architecture The following diagram illustrates the Delegated Signing architecture: The key shares (labeled 1 through 5 above on the right side) are encrypted and stored in our decentralized signer network. Our signers implement leading peer-reviewed cryptographic protocols for distributed key generation and threshold signatures. They are spread across Tier 3+ data centers and different geographical regions to ensure high levels of service availability, fault-tolerance, and business continuity. Our decentralized custody network will be extended to include permissioned partners who are compensated for generating keys and signing transactions. No single entity will hold a threshold of key shares for any given wallet (i.e., the total number of key shares required to move assets on-chain). Hence, Dfns can guarantee high levels of governance neutrality, demonstrate that the private key does not exist in its full format, and ensure that no single party can move assets unilaterally. Instead, our design scheme suggests that control of the API is the new proof of custodianship. This control is dictated by the combination of an access token and a signing secret as described in the [authentication introduction](/api-reference/auth). Using Dfns, platforms can decide whether they want to keep the API control on-premise (custodial mode) or delegate it to their end-users’ devices exempting themselves from any custodial responsibility (end-user-custodial mode, or self-custodial mode). This architecture ensures that transactions can only be executed via the API. Therefore, API security becomes paramount. The Dfns security team has built a multi-level authentication, authorization, and governance architecture to ensure full accountability of API usage. At the heart of this architecture are the signing secrets (illustrated with the key icons on the left side of the diagram above). Dfns’ [Authentication](/api-reference/auth) requires that all requests to the API capable of changing state in the system or on chain (POST, PUT, and DELETE requests specifically) must be signed by a secret known only to the custodian of the assets. The authentication service validates the signature and writes an immutable log of the transaction, cryptographically proving the source of the API call. ### Delegated Signing User Experience In a Delegated Signing configuration, our client delegates custodianship to their end-user by building an onboarding flow in which the user generates and persists a signing secret on their device. In order to enable frictionless user experiences, we have integrated the [WebAuthn 3.0](http://webauthn.guide) passwordless open protocol. WebAuthn is natively integrated into all major browsers and mobile operating systems, exposing seamless access to biometrics, pin codes, and Yubikeys. This enables an onboarding flow such as the following: 1. The user registers with your product using the credentials of their choice including social login. 2. They create a wallet, establishing signing credentials via biometrics. This is executed via a simple Dfns API call. 3. They purchase or transfer assets into the wallet. When they want to execute an outbound transaction, they verify via biometrics again, silently signing the transaction on their device. The Delegated Signing architecture relieves the Dfns client from the regulatory burden of financial custodianship by ensuring that they do not have the ability to manipulate the assets of their users on chain. This is cryptographically proven given that they never have access to the signing secret kept by their user which is required to execute transactions against the API. ### Delegated Signing Wallet Recovery Most self-custodial wallets like Metamask or Ledger require users to indefinitely safekeep a 24-word seed phrase to guarantee access to their assets. Even early adopters of cryptocurrencies who are familiar with the technical constraints of self-custodial wallets have proven time and again incapable of managing keys safely, as seen most recently in the unfortunate case of [a bitcoin core developer losing his funds](https://cointelegraph.com/news/bitcoin-core-developer-claims-to-have-lost-200-btc-in-hack). By leveraging an API signing secret as a proxy for the blockchain private key, the risks described above are substantially mitigated. Unlike a blockchain private key, the signing secret is not immutable. If it is stolen, it can be revoked. If it is lost, it can be re-established. See below a table comparing the properties between a blockchain-bound Private Key and an API Key. Of course, there are trade-offs. This architecture creates new potential attack vectors for bad actors. For instance, a hacker may impersonate a legitimate user in order to gain access to their wallet via the recovery process. In order to mitigate this risk, Dfns provides guidance on recovery mechanisms which our clients can implement. For example, Dfns clients can implement "biometric recovery" by encouraging users to [create secondary credentials](/guides/registering-a-new-passkey-credential) on alternate devices. In this way, if a user lose access to their primary device (for example, their phone), they can still access their wallet via a secondary device like their laptop. Additionally, similar to password manager solutions like 1Password, end-users can receive a recovery code which they are instructed to keep securely offline. Should the user lose their device, this code can be provided via the Dfns client’s application in order to re-establish access to their wallet. Alternatively, some Dfns clients require their end-users to go through a KYC process. This process can be re-initiated for users who have lost access to their devices in order to validate their identities and re-establish credentials. The KYC vendor in this case serves as a gate to a recovery secret the user can access once checks are passed that can be used to sign a recovery challenge. ### Questions on Delegated Signing Delegated Signing is an innovative approach to optimizing the security and user experience of noncustodial wallets. Dfns is committed to partnering with our customers to onboard the next billion users through familiar technologies like biometrics. Have a follow up question on Delegated Signing? Feel free to reach out to us on [https://support.dfns.co](https://support.dfns.co) # Using Hardware Security Modules (HSMs) Source: https://docs.dfns.co/advanced/deployment-models/hsm ## Overview 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. ## Detailed Architecture and Integration ### Signing Server Overview The Dfns Signing Server 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 Signing Server operates as a bridge, handling key generation and signing requests while ensuring state-of-the-art security and operational flexibility.The Signing Server has two primary functionalities: 1. **Polling Dfns APIs**: The Signing Server continuously polls the Dfns APIs to retrieve requests for generating new keys or signing transactions using existing keys. The connection between the Signing Server 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 Signing Server translates API requests into PKCS#11 commands to interact with the HSM. This abstraction allows the Signing Server to support diverse HSM models without requiring specific hardware configurations. ### Stateless 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. The stateless workflow is as follows: * **Key Generation**: 1. The Signing Server receives a key generation request from the Dfns APIs. 2. It forwards the request to the HSM, which generates a new cryptographic key. 3. The HSM wraps (encrypts) the key using its root key, producing a wrapped key. 4. The Signing Server retrieves the wrapped key and stores it in a secure database for backup and future use. * **Transaction Signing**: 1. The Signing Server receives a signing request from the Dfns APIs, including the payload to be signed. 2. It retrieves the corresponding wrapped key from the database. 3. The Signing Server sends the wrapped key and the payload to the HSM. 4. The HSM unwraps (decrypts) the key using its root key, performs the signature operation, and returns the signed payload to the Signing Server. 5. The Signing Server forwards the signed payload to the Dfns APIs for processing. This stateless design ensures that the HSM does not need to maintain key state, enabling compatibility with a broad range of HSMs and simplifying key management. ### Database Backup and Disaster Recovery The wrapped keys stored in the database are encrypted with the HSM’s root 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 root key can access the wrapped keys from the database, allowing seamless recovery without key loss. ### Horizontal Scaling and Redundancy The Signing Server and HSM integration are designed for horizontal scaling to support high availability and business continuity. Customers can deploy multiple HSMs and Signing Server instances to handle increased load or ensure redundancy. The only requirements for scaling are: * All HSMs must be provisioned with the same root key to unwrap keys consistently. * All Signing Server 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. ### Deployments Options The Signing Server is a flexible component that can be deployed on the customer’s infrastructure, offering multiple packaging and deployment options: * **Container Image**: The Signing Server 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 Signing Server is available as a standalone binary, compatible with common operating systems. * **Co-Located Deployment**: The Signing Server 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. ### HSM Administration and Security Dfns does not participate in the administration or management of the customer’s HSM. All HSM-related operations, including provisioning, configuration, and root 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. ### Integration Steps To integrate an HSM with Dfns, customers must perform the following steps: 1. **Obtain the Signing Server**: Contact Dfns to acquire the Signing Server component, available as a container image or standalone binary. 2. **Generate mTLS Certificates**: Sync with Dfns to configure mTLS certificates for secure communication between the Signing Server and Dfns APIs. Ensure that the certificates are properly provisioned and validated. 3. **Deploy the Signing Server**: Install and configure the Signing Server on the customer’s infrastructure, ensuring connectivity to the HSM and the wrapped key database. 4. **(Optional) Provision the HSM**: If using a new HSM, configure the HSM with a root key and ensure it supports PKCS#11. If using multiple HSMs, provision them with the same root key. 5. **Run the Signing Server**: Start the Signing Server, 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. ### Security Considerations * **mTLS Authentication**: The use of mTLS between the Signing Server 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 root 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 Signing Server 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 our MPC 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. Whether you prefer a simple and secure hands-off approach or require maximum control over your cryptographic operations, Dfns has a model to match. ### The Models at a Glance We offer three primary deployment models. Each provides the same core security of our MPC-TSS protocol but varies in operational management and control. #### Dfns Cloud (Fully-Managed) ☁️ 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 Cloud 🤝 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. * **You get:** Shared security responsibility and direct control over transaction finality. #### On-Premise (Self-Hosted) 🏢 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. * **You get:** Maximum control over your keys and infrastructure. ### Enhancing Security with On-Premise HSMs 🛡️ For organizations seeking the highest level of assurance, Dfns supports integrating customer-owned **Hardware Security Modules (HSMs)**. Customers using the **Hybrid Cloud** or **On-Premise** models can store their key shares within their own FIPS 140-2 compliant HSMs. This adds a layer of physically-enforced, tamper-resistant security to your cryptographic operations, ensuring your key shares never leave the protected boundary of your hardware. ### 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: Using HSMs](/advanced/deployment-models/hsm) * [Detailed Guide: On-Premise Deployment](/advanced/deployment-models/on-premise-deployment) # On premise deployment Source: https://docs.dfns.co/advanced/deployment-models/on-premise-deployment With Dfns you can deploy the signers or the HSM signing server on your infrastructure. This is high level overview of the on premise deployment: Interested? please contact the Dfns support team at [https://support.dfns.co](https://support.dfns.co). # Interoperability Source: https://docs.dfns.co/advanced/interoperability 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). Our goal is to eliminate all single points of failure (SPOFs) associated with blockchain private keys by never exposing those private keys to anyone. In some circumstances, however, you may need to import or export an existing wallet and its private key into the Dfns infrastructure, instead of creating a brand new wallet with Dfns and transfer funds to it. As an example, you might want to keep an existing wallet if its address is tied to a smart contract which you don't want to re-deploy. In such a case, Dfns exposes import and export endpoints. ## Import a wallet Use /wallets/import: [Import a Wallet](/api-reference/wallets/import-wallet) in conjunction with our [import SDK](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/sdk/import-wallet). Note this is intended to be used only to migrate wallets when first onboarding onto the Dfns platform. This endpoint is not enabled by default. [Contact support](https://support.dfns.co) to have it activated. **Dfns can not guarantee the security of imported wallets** We have no way to control who had access to the private key prior to import. For this reason, this feature is restricted to Enterprise customers who have signed a contractual addendum limiting our liability for imported wallets. Please [contact support](https://support.dfns.co) for more information. ## Import a key Use /keys/import: [Import a Key](/api-reference/keys/import-key) in conjunction with our [import SDK](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/sdk/import-wallet). Note this is intended to be used only to migrate wallets when first onboarding onto the Dfns platform. This endpoint is not enabled by default. [Contact support](https://support.dfns.co) to have it activated. **Dfns can not guarantee the security of imported keys** We have no way to control who had access to the private key prior to import. For this reason, this feature is restricted to Enterprise customers who have signed a contractual addendum limiting our liability for imported keys. Please [contact support](https://support.dfns.co) for more information. ## Export a key Use /keys/\{keyId}/export: [Export a Key](/api-reference/keys/export-key) in conjunction with our [export SDK](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/sdk/export-wallet). **Dfns can not guarantee the security of exported keys** We have no way to control blockchain transactions once the single point of failure has been reconstituted. For this reason, this feature is restricted to customers who have signed a contractual addendum limiting our liability for exported keys. Additionally, exported keys can no longer be used to sign within the Dfns platform. Please [contact support](https://support.dfns.co) for more information. # Non-custodial wallets Source: https://docs.dfns.co/advanced/non-custodial-wallets Give your end users sole and full control over their digital assets Dfns enables a unique configuration called **Delegation** in which control of a wallet is delegated from your team to your end user (regardless of whether they are a consumer or a corporate entity). Your users will have to sign actions (transfers, etc.) themselves using their own passkeys, from your app or website: you and your team lose control of the wallet, and your end users gain full control. ## White-label Dfns Delegation allows you to hide the fact that your users are using Dfns as their wallet provider and only use our API for wallet management, in the background. Using Delegated user management, you register your end users and then log them in to Dfns from your own backend when they need to interact with their wallets. This is only a backend authentication, the users don't see anything of Dfns, we just tell you what to show and ask them, for instance when they actually have to sign an action using their passkey. In this way, you retain full control over the user experience, and Dfns remains hidden in the backend. No email from Dfns, no Dfns branding, just your app and your brand. End Users are a first class citizen in Dfns. Once registered (by you) they could use the Dfns APIs directly if they access their auth token. Please carefully review the policies and controls you have in place. ## Get started Read more on [Delegated Signing](/advanced/delegated-signing), and start implementing Wallet Delegation in your application: [Developer Guide](/developers/guides/wallet-delegation) # 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. # 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 ## User Recovery Both `Employee` and `Enduser` user types can recover their Dfns accounts by creating recovery credentials. `Employees` connected with your organization are provided a recovery kit when they register on the Dfns dashboard. They should store this recovery kit securely offline. If they need to recover their account credentials, they can do so at [https://app.dfns.io/recover](https://app.dfns.io/recover) by providing the information from the kit and a verification code proving they still have access to their email. Alternatively, an existing organization user with administrative permissions can deactivate and re-create their account using a different email address. It is possible to create as many recovery credentials as you want. Any recovery credential can be used to recover a User. Once a recovery credential is used, all the user credentials (recovery and regular) are invalidated for security reasons. The user needs to create at least one new recovery credential, this can be done during the recovery process (see [Recover User](/api-reference/auth/account-recovery)). `Enduser` recovery can be built by Dfns clients as described below. The process is as follows: 1. Construct the `newCredential` object, using the challenge obtained from either the [Create Recovery Challenge](/api-reference/auth/create-recovery-challenge) endpoint. 2. Serialize the `newCredential` object to JSON and then base64url-encode the resulting JSON string. This *base64url-encoded* string will serve as the challenge for the `recovery.credentialAssertion` object. 3. Construct the `recovery.credentialAssertion` object, using the *base64url-encoded* string generated in step 2 as its challenge. 4. Recover User: use `POST /auth/recover/user` to recover a user, using a recovery credential. The `recovery.credentialAssertion.clientData` field's challenge must be the *base64url-encoded* representation of the `newCredential` object. After successfully recovering the user, all of the user's previous credentials and personal access tokens will be invalidated. ## End User Recovery You can decide where in your UX flow to create recovery credentials for your end users. Depending on the value of assets and the users' ability to create credentials from multiple devices (which is recommended), you may want to make this mandatory upfront or optional later in your flow. In order to initiate recovery, however, an end-user must have credentials already registered with the system. Here are the general steps required to perform an end-user recovery: * Verify the identity of your user via your existing authentication methods, KYC, etc. * Call the [Create Delegated Recovery Challenge](/api-reference/auth/create-delegated-recovery-challenge) endpoint from a service account (`DfnsApiClient.auth.createDelegatedUserRecovery` in the SDK). * Dfns generates a new registration context, so that you can create the user’s new credentials. Forward this to your user. * The user creates a new credential (and optional new recovery credential) * The user signs the new credential(s) with their existing recovery credential, and sends the new credential(s) + signature to Dfns to [Recover](/api-reference/auth/recover-user) endpoint (`DfnsDelegatedApiClient.auth.createUserRecovery` in the SDK) * Dfns verifies the signature is valid * Dfns archives all of the user’s current credentials (regular + recovery) * Dfns adds the user’s new credentials The following diagram explains the flow to recover an end 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 (usernamless 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](/developers/guides/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.