Dfns API Documentation
  • đź‘‹Welcome
  • Getting Started
    • Onboarding to Dfns
    • Dfns Environments
    • Core API Objects
    • Supported Assets
    • Postman
    • Dfns SDKs
    • Dashboard Videos
  • API Docs
    • Introduction
    • Authentication
      • Delegated Authentication
        • Delegated Registration
        • Delegated Registration Restart
        • Delegated Login
      • User Action Signing
        • Create User Action Signature Challenge
        • Create User Action Signature
      • Registration
        • Create User Registration Challenge
        • Complete User Registration
        • Complete End User Registration with Wallets
        • Resend Registration Code
        • Social Registration
      • Login
        • Create User Login Challenge
        • Complete User Login
        • Social Login
        • Logout
        • Send Login Code
      • Users
        • List Users
        • Create User
        • Get User
        • Activate User
        • Deactivate User
        • Archive User
      • Service Accounts
        • List Service Accounts
        • Create Service Account
        • Get Service Account
        • Update Service Account
        • Activate Service Account
        • Deactivate Service Account
        • Archive Service Account
      • Applications
        • List Applications
        • Create Application
        • Create Server-Signed Application
        • Get Application
        • Update Application
        • Activate Application
        • Deactivate Application
        • Archive Application
      • Personal Access Tokens
        • List Personal Access Tokens
        • Create Personal Access Token
        • Get Personal Access Token
        • Update Personal Access Token
        • Activate Personal Access Token
        • Deactivate Personal Access Token
        • Archive Personal Access Token
      • Credentials
        • Credentials Overview
        • API Reference
          • Create Credential Code
          • Create Credential Challenge
          • Create Credential Challenge With Code
          • Create Credential
          • Create Credential With Code
          • Deactivate Credential
          • Activate Credential
          • List Credentials
      • Recovery
        • Send Recovery Code Email
        • Create Recovery Challenge
        • Create Delegated Recovery Challenge
        • Recover User
    • Wallets
      • Create Wallet
      • Update Wallet
      • Delete Wallet
      • [deprecated] Delegate Wallet
      • Get Wallet by ID
      • List Wallets
      • Get Wallet Assets
      • Get Wallet NFTs
      • Get Wallet History
      • Tag Wallet
      • Untag Wallet
      • Transfer Asset
      • Get Transfer Request by ID
      • List Transfer Requests
      • Sign and Broadcast Transaction
        • Algorand
        • Aptos
        • Bitcoin / Litecoin
        • Canton
        • Cardano
        • EVM
        • Solana
        • Stellar
        • Tezos
        • TRON
        • XRP Ledger (Ripple)
      • Get Transaction Request by ID
      • List Transaction Requests
      • [deprecated] Generate Signature
      • Advanced Wallet APIs
        • Import Wallet
        • [deprecated] Export Wallet
    • Fee Sponsors
      • Create Fee Sponsor
      • Get Fee Sponsor
      • List Fee Sponsors
      • Activate Fee Sponsor
      • Deactivate Fee Sponsor
      • Delete Fee Sponsor
      • List Sponsored Fees
    • Keys
      • Create Key
      • Update Key
      • Delete Key
      • Delegate Key
      • Get Key by ID
      • List Keys
      • Generate Signature
        • Algorand
        • Aptos
        • Bitcoin / Litecoin
        • Cardano
        • Cosmos Appchain
        • EVM
        • Solana
        • Stellar
        • Substrate (Polkadot)
        • Tezos
        • TON
        • TRON
        • XRP Ledger (Ripple)
      • Get Signature Request by ID
      • List Signature Requests
      • Advanced Key APIs
        • Import Key
        • Export Key
        • Deterministic Derivation
    • Networks
      • Estimate fees
      • Read Contract
      • Validators
        • Create Validator
        • List Validators
    • Policy Engine
      • Policies Overview
      • API Reference
        • Create Policy
        • Get Policy
        • List Policies
        • Update Policy
        • Archive Policy
        • Get Approval
        • List Approvals
        • Create Approval Decision
    • Permissions
      • Permissions Overview
      • API Reference
        • Get Permission
        • List Permissions
        • Create Permission
        • Update Permission
        • Archive Permission
        • Assign Permission
        • Revoke Permission
        • List Permission Assignments
    • Webhooks
      • Create Webhook
      • Get Webhook
      • List Webhooks
      • Update Webhook
      • Delete Webhook
      • Ping Webhook
      • Get Webhook Event
      • List Webhook Events
    • Dfns Change Log
    • API Errors
  • Integrations
    • Exchanges
      • Kraken
      • Binance
      • Coinbase Prime
      • API Reference
        • Create Exchange
        • List Exchanges
        • Get Exchange
        • Delete Exchange
        • List Exchange Accounts
        • List Exchange Account Assets
        • Create Exchange Deposit
        • Create Exchange Withdrawal
    • AML / KYT
      • Chainalysis
    • Staking
      • API Reference
        • Create Stake
        • Create Stake Action
        • List Stakes
        • List Stake Actions
        • get Rewards
    • Fiat On/Off-Ramps
    • Account Abstraction on EVMs
  • Advanced Topics
    • Authentication
      • API Authentication
      • Request Headers
      • Credentials
        • Generate a Key Pair
        • User Credentials
        • Access Token Credentials
        • Storing WebAuthn Credentials in Password Managers
      • Request Signing
      • API objects
    • Delegated Signing
    • API Idempotency
    • FAQ
  • Guides
    • Passkey Settings - Migration guide
    • Keys & Multichain - Migration Guide
Powered by GitBook
On this page
  • TLDR;
  • First, some context
  • Motivation for the change
  • How to migrate ?
  • What’s Next ?
  1. Guides

Passkey Settings - Migration guide

Last updated 3 months ago

TLDR;

We’re gonna remove the rpId and origin properties from Dfns “Applications”, and create a separate “Passkey Settings” page to configure passkey origins. As a result, an upcoming breaking change in the API is introduced, and require our customers to do a minor update in their client-side code (in web apps or mobile apps). The change is about specifying the relying party ID explicitly in those apps.


First, some context

On Passkeys & Relying Party

With Dfns, users can use to authenticate with our systems. A passkey – also known as “Fido2 credential” or “WebAuthn credential” – is a cryptographic key created and stored securely on a user’s device: a laptop, a phone, an external device like Yubikey, it can also be stored on the cloud, on password manager etc. Passkeys offer a more secure, yet better UX for user authentication than good-old passwords. From the user’s perspective, it often takes the form of a simple biometric check like face ID / fingerprint.

By design – for security reasons – any passkey is scoped to a “Relying Party ID”, specified during creation of the passkey. The Relying Party ID (rpID, for short) is essentially a domain owned by you – the organisation – under which your web app is hosted, or to which your mobile app is tied (eg. acme.org, tesla.com, etc.). This rpId defines on which app – or set of apps – a given passkey will be usable by a user.

As an example, if you want a user to use the same passkey in:

  • a web app https://foo.acme.com

  • a web app https://bar.acme.com

  • an IOS mobile app

  • an Android app

then the rpId specified during creation of the passkey must be the root domain “acme.com“

Note: mobile apps must be “associated with” the domain acme.com. IOS and Android setup is slightly different, but involves hosting a .well-known file on your domain, to “prove domain is yours and associate the mobile app“, eg. https://acme.com/.well-known/assetlinks.json for , or https://acme.com/.well-known/apple-app-site-association for .

On Dfns Applications

  • First function was to be an additional permission layer on top of the User’s permission. Any API request is checked against the intersection of both the Application permissions & the User permissions. That would allow custom setups when an organisation wants to setup different applications with different levels of permissions

  • Second function was to specify which domain (rpID) & origin was the Application expected to be used in, and therefore, validate that passkeys used in that application match the rpId specified on the Application used, and are indeed used from the specified origin.

So, with that design, the app ID you use in the Dfns API request also determines which passkey is allowed to be used.


Motivation for the change

After gathering our customer’s feedback, it turns out Dfns Applications are more a source of confusion and complication than anything else, especially newcomers.

The main reason is that the relationship between the Application and the Passkey is not obvious. We – Dfns – thought that tying those things together would hide away the complexity from users and make it more seemless. Turns out that people were more confused as to what those things meant, and the relationship between them, and in turn, how to set it up properly.

Also, since we offer different kind of credentials to authenticate (like raw asymmetric keys), but the rpID / origin setup on Applications is only relevant in the context of a passkey credential, that could add to the confusion.

Another reason is that the setup was a bit cumbersome if you had several several web-apps + mobile apps to setup, as you needed to create several Dfns Applications, and use the right Application ID from the right place in order for everything to work out properly alongside with Passkeys.

We believe that the domain (Relying Party ID) that you choose to create your passkeys in your client apps, should be in your control, client-side. The only reason Dfns needs to know about it, is to “whitelist” these domains you wanna use.

So we decided to update that design a bit, and extract the rpId and origin properties outside of Dfns Applications, and instead introduce separate “Passkey Settings” accessible through Dfns dashboard.

Only future will tell if we go a step further, and also decide to revise our Application model + the required Application ID passed in any Dfns API request (as header). But regardless, this current change was a necessary first step.


How to migrate ?

To whitelist a new domain (rpId) where your users need to create/user passkeys, you can now go to Dfns dashboard, into Settings > Passkeys, and whitelist the domain from there:

When whitelisting a Relying Party ID, every origin in the “realm” of this rpID (all subdomains + associated mobile apps) will be allowed for passkeys to be used. That’s what the wildcard "*" means in the screenshot above.

In case you need to specifically whitelist only a specific subset of origins from which a passkey should be used – for most use cases, this shouldn’t be necessary – you can specify “only specific origins” in the whitelisting form, and specify them:

All rpIds previously specified in your existing Dfns Applications will already be pre-filled in these new Passkey Settings, with origins = *.

When you create a new Dfns Application from our Dashboard, you won’t be able to specify rpId + origin anymore. Instead, if your goal is only to whitelist a new domain, you won’t necessarily need to create a new Application, but rather you’ll need to add the new rpId in the “Passkey Settings” page.

If you still create a new Application (so without rpId attached), your client-side code needs to account for that (see how below).

After the transition period, a breaking change will be introduced in the API: rpId + origin properties will be entirely removed from all Applications (even old ones). As a result,rpID will not be included in challenge payloads anymore. So far, your client side code may have relied on this rpID being returned in the challenge payload, to pass it along to the WebAuthn client during passkey creation / usage.

To account for this upcoming breaking change, your client-side app code must stop relying on the rpId returned in the challenge payloads. Instead, the relying party rather needs to be specify explicitly in your client-side code, during passkey creation / usage.

For people using our SDKs, it basically means upgrading the SDK, and make one change (see below).

➡️ For web apps:

// before
const signer = new WebAuthnSigner()

// after
const signer = new WebAuthnSigner({
  relyingParty: { id: 'acme.com', name: 'Acme' }
})

If you have a web app and are interacting with WebAuthn yourself (without using our Typescript SDK), you must provide the relying party in the navigator.credentials.create(...) and navigator.credentials.get(...) calls (if you didn’t already). Eg

// passkey creation
const cred = await navigator.credentials.create({
  publicKey: {
    ...,
    rp: { id: 'acme.com', name: 'Acme' }
  }
})

// passkey usage
const cred = await navigator.credentials.get({
  publicKey: {
    ...,
    rpId: 'acme.com'
  }
})

➡️ For React Native Apps:

// before
const signer = new PasskeySigner()

// after
const signer = new PasskeySigner({
  relyingParty: { id: 'acme.com', name: 'Acme' }
})

➡️ For Flutter Apps:

// before
final passkeysSigner = PasskeysSigner()

// after
final passkeysSigner = PasskeysSigner(
    relyingPartyId: PASSKEY_RELYING_PARTY_ID,
    relyingPartyName: PASSKEY_RELYING_PARTY_NAME
);

➡️ For IOS Apps:

// before
let signer = PasskeysSigner()

// after
let signer = PasskeysSigner(relyingPartyId: "acme.com")

➡️ For Android Apps:

Same principle than above: your client-side apps code must not rely on the ****rpId ****returned in the challenge payloads, and you rather need to specify the relying party explicitly, during passkey creation / usage.

Last point: from now on, don’t necessarily need to use several Dfns Application IDs in your code, you can always use the same App ID if you want to (if all Dfns Apps you use have the same set of permissions).


What’s Next ?

Hopefully this change makes setting up passkeys with Dfns more transparent and less confusing, as well as making it easier to setup passkeys for cross-subdomain usage (rpId needs to be common root domain).

You might be wondering if later it will would be possible to use passkeys cross-domain. Meaning, not just cross-subdomains of the same root domain (this is already possible), but across completely different root domains. Eg. use the same passkey both in acme.com and tesla.xyz. This matter, called “Related Origins” is being discussed in WebAuthn specification, and as the community converges to a new spec to allow this, it will progressively be supported in all platforms.

When Related Origins becomes widely implemented in major platforms, from Dfns perspective, no additional changes will be needed for you to support cross-root-domain passkeys. You’ll just need to follow the new spec to associate those related domains together, and then whitelist a new domain in Dfns.

More on “Related Origins” on the following links:

Every request to Dfns API takes an Application ID in the x-dfns-appid header. were originally designed to have a dual function:

During a transition period of N months, if you keep using Applications created before this change (which still have a rpId attached), the API won’t introduce a breaking change, as the App rpId will still be included in every challenge endpoint payloads (eg or ).

If you used our in a web app, you must upgrade to the newest version of @dfns/sdk and @dfns/sdk-browser, (version 0.6.0) where WebauthnSigner was updated to take in the relying party in the constructor explicitly:

If you used our in a react native app, you must upgrade to the newest version of @dfns/sdk and @dfns/sdk-react-native (0.6.0) where PasskeysSigner was updated to take in the relying party explicitly in the constructor:

If you used our , you must upgrade to the newest version of the package (0.0.5) where PasskeysSigner was updated to take in the relying party explicitly in the constructor:

If you used the as an example / source in your IOS app, you must get the latest changes to it, and then:

You can also read more on the official WebAuthn spec .

Passkeys
Android
IOS
Applications
Create Delegated Registration Challenge
Create User Action Challenge
Typescript SDK
Typescript SDK
Flutter SDK
Swift SDK
https://passkeys.dev/docs/advanced/related-origins/
https://github.com/w3c/webauthn/wiki/Explainer:-Related-origin-requests
https://chromestatus.com/feature/4635336177352704
here