
Introducing major upgrades to Dfns authentication with WebAuthn: Secure Payments, Multi-subdomain support, and Conditional UI
At Dfns, authentication is foundational for all secure operations done inside our platform. We’ve long relied on WebAuthn to offer phishing-resistant, passwordless access to our services. But until recently, using WebAuthn for anything beyond basic login introduced real friction for developers and users alike. Today, we’re rolling out a major upgrade to our WebAuthn platform with three significant improvements:
- Secure Payment Confirmation (SCP) for signing transactions
- Multi-origin support across applications and platforms
- Conditional UI for seamless, non-intrusive passkey login
These changes are backed by a significant architectural refactor to our WebAuthn configuration model. Read on to understand how this impacts your integration and unlocks new capabilities.
Tying authentication to intent with Secure Payment Confirmation
WebAuthn is often used for login, but its potential goes far beyond session authentication. It’s fundamentally a public-key signature protocol and that makes it an excellent tool for transaction approval. We’ve now integrated Secure Payment Confirmation (SCP) into our WebAuthn flow. This allows users to approve a specific payload (e.g. payment, transfer, or contract execution) using their authenticator. Instead of simply authenticating a session, they’re signing intent. WebAuthn authenticators (e.g., Touch ID, security keys) are used to sign not just login challenges, but transaction payloads, adding a hardware-backed proof that the user explicitly approved the operation.
This is particularly important in regulated environments, fintech apps, and decentralized protocols where accountability, explicit user consent, and strong attribution matter. It reduces risk, eliminates overbroad authorization scopes, and moves WebAuthn from “secure login” to “secure execution.”
Here’s what SCP enables:
- A user can be asked to approve a $250,000 transfer by signing the transaction hash with a WebAuthn authenticator.
- The server validates that the signature was produced by a device tied to the user’s passkey and that it covers the expected payload.
- A record of this approval—linked to both device and user—is retained for auditability.
Benefits:
- Phishing-resistant payment flows
- Zero-trust user attribution: Know exactly who signed what, when, and from where
- No passwords or shared secrets—just cryptographic keys stored securely on user-controlled devices
- No more "are you sure?" popups—user intent is captured via hardware
- Ties authentication to specific actions, not just sessions
- Can be enforced at the API level (e.g. sign before broadcast)
How Dfns supports it:
- We’ve extended our WebAuthn challenges to support action payloads (like transactions)
- SCP validation ensures the authenticator signs that specific payload
- Our API can generate and verify signatures using native WebAuthn APIs
Refactoring WebAuthn beyond single-origin applications
Modern day apps don’t live siloed on a single domain. Whether you run multi-region platforms, white-label deployments, or hybrid web/mobile stacks, your passkey system needs to be flexible. Previously, Dfns Applications were tightly coupled to a single:
- Relying Party ID (
rpId
): The domain associated with the passkey (e.g.,acme.com
) - Origin: The exact web origin or app hash from which requests come (e.g.,
https://foo.acme.com
,android:apk-key-hash:abc123
)
Each Application was allowed only one rpId
+ one origin, which caused:
- Friction for developers managing multiple subdomains or frontend platforms
- Redundant Applications and misused API keys
- Inability to scale across customer subdomains or mobile integrations
We’ve introduced organization-level WebAuthn settings so you can now:
- Define multiple relying parties and associated origins
- Multiple web subdomains (e.g.,
foo.acme.com
,bar.acme.com
) - Support wildcards like *.
cust.acme.com
- Separate authentication scope (
rpId/origin
) from authorization logic (application permissions) - Native mobile apps via App Hashes
We now validate passkeys by:
- Extracting the
rpIdHash
from the authenticator data - Matching it against your org’s allowed relying parties
- Validating the origin, if specified, against the corresponding list
If no origin is specified for an rpId
, we default to allowing all origins under that domain simplifying onboarding and passkey reuse. You can still add origin restrictions if you want fine-grained control (e.g., allow foo.acme.com
but not bar.acme.com
for the same passkey).
Benefits:
- Simpler integration for multi-tenant or cross-platform apps
- Fewer API keys and configs to manage
- Scalable and flexible as your product architecture evolves
This design also unlocks real scalability. It reduces the number of artifacts you need to maintain and gives your team full control over how passkeys are created, validated, and reused. Developers can now explicitly specify the rpId
they want to use when creating or validating credentials. This gives frontends more clarity and reduces reliance on hidden backend configuration.
Seamless sign-in without interruptions with Conditional UI
WebAuthn’s biggest user experience issue was its modality. Calling navigator.credentials.get()
would immediately launch a full-screen system dialog, even if no credential was available. This interrupted the user flow, created dead-ends, and made passwordless adoption hard.
Conditional UI is a browser-native feature that only shows the WebAuthn prompt if a matching passkey is silently available. It integrates directly with the browser’s autofill prompt, alongside saved passwords. With this feature enabled, browsers only display a WebAuthn sign-in prompt if a valid, discoverable credential is already available. The prompt appears directly within the browser’s autofill UI, alongside saved passwords, without disrupting the page or triggering a system-level dialog.
What users see:
- If a passkey exists → they can click and authenticate instantly
- If not → no dialog is shown, and password fallback remains smooth
Benefits:
- No dead-end modals or user confusion
- Easier onboarding to passkeys
- Invisible fallback to traditional login
- Perfect for "passwordless first" strategies
You can activate conditional UI by passing mediation: "conditional"
to navigator.credentials.get():
navigator.credentials.get({
mediation: "conditional",
publicKey: {
challenge: ...,
...
}
});
Browsers will then surface WebAuthn credentials in the autofill menu but only if discoverable credentials are registered. Note: Conditional UI currently supports only discoverable credentials (i.e., passkeys that don’t need a credential ID to be queried).
This is a major usability improvement, especially for teams transitioning from password-based to passkey-based authentication. It lets users opt into passwordless login when possible, without removing fallback paths. This feature is supported across major browsers and aligns with best practices in privacy-preserving credential discovery.
How it all comes together
To enable all these capabilities, we’ve refactored our backend validation logic and WebAuthn flow as follows:
- Relying parties (
rpId
) and allowed origins are now defined at the organization level, not per Application. - Our backend extracts the
rpIdHash
from the credential’s authenticator data and validates it against your org’s whitelist. - The
origin
from the assertion’s client data is also validated—either against an allowlist you define or accepted by default under therpId
. - Fallback logic ensures backward compatibility with applications still using the old model.
- Our APIs allow developers to specify the expected
rpId
andname
client-side, ensuring full control and visibility.
This makes the system more predictable, scalable, and aligned with upcoming standards—such as cross-TLD passkeys, which rely on well-known bindings and broader domain-level trust relationships.
Best practice recommendations for WebAuthn integration
As you adopt the new capabilities, here are a few practices we recommend to improve resilience and user experience:
- Encourage users to register multiple credentials, especially one roaming authenticator like a smartphone or hardware key. This prevents lockouts if a device is lost or reset.
- Support cross-device login flows using QR-code based interactions or roaming authenticators.
- Provide recovery flows that allow users to re-establish trust using fallback credentials and in-app guidance for re-enrolling credentials after loss.
- Enable Conditional UI in your login forms to provide a seamless experience and reduce modal friction.
- Specify the
rpId
andorigin
explicitly when integrating WebAuthn, particularly in mobile apps or multi-subdomain environments.
These changes mark an important step toward making passkeys viable across all kinds of financial products—from neobanks to stablecoin wallets, institutional custody, and trading interfaces. WebAuthn is a powerful protocol, but its real strength comes from tight integration with your product’s architecture, transaction flows, and UX. With Secure Payment Confirmation, Multi-Origin Support, and Conditional UI, we believe we’ve removed the biggest pain points in deploying WebAuthn at scale.
To get started:
- Review the Dfns Authentication Docs
- Contact us to configure SCP or org-level WebAuthn settings