Platform
Platform
Drop-In Authentication
Passkeys
Phishing-resistant, FIDO2/WebAuthn
Biometric authentication
Face and device-native biometrics
WhatsApp OTP
Global reach, lower cost than SMS
Email OTP
Universal second factor
App push authentication
Native device push notifications
Palm biometrics
Contactless identity verification
All authentication methods
KEY FEATURES
No-code rules engine
Step-up auth, risk policies, alerts
User observability
Audit trails, dynamic linking
Risk-based authentication
Adaptive MFA by context
Session management
Persistent sessions across channels
Digital credentials API
Verify sovereign digital IDs
Pre-built UI
Fastest deployment path
Passkeys
Deploy phishing-resistant passkeys across web and mobile in days
Solutions
Solutions
USE CASE
Account Takeover Prevention
Stop ATO without adding friction
Go Passwordless
Replace passwords with passkeys
Account Recovery
Secure self-service recovery flows
Call Centre Authentication
Verify callers without KBA
SMS Cost Optimisation
Cut OTP costs up to 90%
Existing Apps (Drop-In)
Add auth without re-architecting
Palm biometric payments
Contactless in-store payments
INDUSTRY
Financial Services & Banking
Secure high-value transactions
Healthcare
Authentication for ePHI access
Loyalty Programs
Protect points and member accounts
ROLE
Engineering
Fast integration, flexible SDKs
Product
No-code flows, conversion insights
Cybersecurity
Risk policies, compliance, audit trails
PricingCustomers
Resources
Resources
LEARN
Blog
Guides
Regulatory
Templates
Docs
COMPANY
About Us
Why Authsignal
Partners
Careers
Security
Contact
INTEGRATIONS
Amazon Cognito
Auth0
Azure AD B2C
Custom identity provider
Duende IdentityServer
All integrations
Docs
Start a trial
Book a callLogin
AUS Flag

Authsignal secures millions of passkey transactions out of our hosted Sydney region.

AUS Flag

Authsignal secures millions of passkey transactions out of our hosted Sydney region.

Join us today!
Right icon
Blog
/
Current article
Duende IdentityServer
Multi-factor authentication
Guides

How to add MFA to Duende IdentityServer with Authsignal

Ashutosh Bhadauriya
⬤
May 14, 2025
Share
How to add MFA to Duende IdentityServer with Authsignal

In this guide, we’ll walk you through how you can add multi-factor authentication (MFA) in your Duende IdentityServer using Authsignal — making your authentication system much more stronger and keeping your users’ data safer.

‍

Why MFA Matters

Adding a second verification step makes your system much more secure. While Duende IdentityServer gives you solid authentication for ASP.NET Core apps, passwords alone aren't enough protection these days. MFA helps defend against hackers who steal passwords or trick your users into revealing their login information.

Let’s explore how we can implement this.

‍

Implementation Approach

One key advantage of this implementation is the ability to progressively transition users from traditional password-based authentication to more robust MFA methods. This ensures minimal disruption to your user experience while enhancing security.

In the following sections, we'll explore:

  • Setting up Authsignal with your existing Duende IdentityServer
  • Configuring the authentication flow

Let's get to building.

‍

Repository Structure

For your convenience, we've published the complete source code with all implementation details on our GitHub repository.

The repo consists of two projects:

  • IdentityServer — The authentication server that handles login requests and MFA challenges
    • Runs on https://localhost:5001
    • Contains the Duende IdentityServer core and Authsignal integration
  • WebClient — A sample client application protected by our enhanced authentication
    • Runs on https://localhost:5002
    • Demonstrates how end users will experience the MFA flow

The code samples in this guide are extracted directly from this implementation.

‍

Setting Things Up

Before we get into the code, you'll need to do a bit of prep work in the Authsignal Portal.

1. Enable the authenticator you want to use (We’ll use Authenticator App for this example)

‍

2. Grab your API keys and region URL

3. Add API key secret to the appsettings.json file of both WebClient and IdentityServer. Tenant ID and URL are required in the client-side JS snippet.

‍

Adding MFA to Your Login Flow

The quickest way to implement MFA is using Authsignal's pre-built UI. But don't worry, you can customize it to match your branding.

Here's how the flow is:

  1. User enters username and password
  2. You validate those credentials
  3. If valid, you redirect to Authsignal's MFA challenge
  1. After completing the challenge, the user gets redirected back to your app

‍

Integrating the MFA Challenge

To implement this flow, we need to modify the login process in IdentityServer. The key integration point is right after validating the user's credentials and before issuing the authentication cookie.

Let's look at how we implement this in the login page's POST handler:

// /src/IdentityServer/Pages/Account/Login/Index.cshtml.cs

public async Task<IActionResult> OnPost()
{
  if (_users.ValidateCredentials(Input.Username, Input.Password))
  {
    var user = _users.FindByUsername(Input.Username);

    var trackRequest = new TrackRequest(
      UserId: user.SubjectId,
      Action: "identity-server-login",
      Attributes: new TrackAttributes(
        Username: user.Username,
        RedirectUrl: "https://localhost:5001/Account/Login/Callback?returnUrl=" + returnUrl
      )
    );

    var trackResponse = await _authsignal.Track(trackRequest);

    if (!trackResponse.IsEnrolled || trackResponse.State == UserActionState.CHALLENGE_REQUIRED)
    {
      return Redirect(trackResponse.Url);
    }
  }
}

‍

  1. First, we validate the user's credentials using IdentityServer's built-in user service
  2. If valid, we retrieve the user object to get their unique identifier
  3. We create an Authsignal TrackRequest with three important parameters:
    • UserId: The unique identifier for this user in your system
    • Action: A string identifier for this authentication action (you can create different actions for different security operations)
    • Attributes: Additional context, including where to redirect after MFA completion
  4. We call Authsignal's Track method, which evaluates the user's MFA status
  5. Based on the response, we either:
    • Redirect to Authsignal's MFA challenge if the user needs to enroll or complete verification
    • Continue with the normal authentication flow if MFA passes silently (e.g., if using device fingerprinting and the risk is low)

For convenience, we are prompting users to enroll for MFA on login if they're not yet enrolled. You can move this enrollment step elsewhere in your user journey too.

The RedirectUrl we pass to the track request will be a callback endpoint that we need to add to IdentityServer to validate the result of the MFA challenge.

Validating the MFA Challenge

When the user completes the MFA challenge, they'll be redirected back to your callback endpoint. This is where you verify the result of the challenge and complete the authentication process.

Implementing the Callback Handler

The callback endpoint needs to:

  1. Validate the token from Authsignal
  2. Check if the challenge was successful
  3. Complete the authentication if verification passed
  4. Redirect to the original destination

Here's how we implement this in our callback handler:

// /src/IdentityServer/Pages/Account/Login/Callback.cshtml.cs

public async Task<IActionResult> OnGet(string returnUrl, string token)
{
  var validateChallengeRequest = new ValidateChallengeRequest(Token: token);
  var validateChallengeResponse = await _authsignal.ValidateChallenge(validateChallengeRequest);
  var userId = validateChallengeResponse.UserId;
  var user = _users.FindBySubjectId(userId);

  if (validateChallengeResponse.State != UserActionState.CHALLENGE_SUCCEEDED)
  {
    // MFA challenge failed - send them back to login
    return Redirect("https://localhost:5001/Account/Login?ReturnUrl=" + returnUrl);
  }

  // Success! Proceed with authentication and issue session cookie
  // [authentication code here]
}

‍

Let's break down this code:

  1. We receive the token parameter from the redirect URL - this contains the verification result
  2. We pass this token to Authsignal's ValidateChallenge method to verify its authenticity
  3. From the response, we extract the user ID to find the corresponding user in our system
  4. We check if the challenge state is CHALLENGE_SUCCEEDED:
    • If not, we redirect back to the login page - this means the user failed verification
    • If successful, we proceed with normal authentication (issuing cookies, etc.)

This callback handler is the critical final piece that completes the MFA flow. After successful verification, you would complete the standard Duende IdentityServer authentication process by issuing the appropriate cookies and redirecting to the requested resource.

Using Email-Based MFA

If you're using email and password as your primary authentication and want to use an email-based Authsignal method (OTP or magic link) as the secondary MFA step, you can avoid asking for the email twice by passing it with your track request:

var trackRequest = new TrackRequest(
    UserId: user.SubjectId,
    Action: "identity-server-login",
    Attributes: new TrackAttributes(
        Email: user.Email,
        RedirectUrl: "https://localhost:5001/Account/Login/Callback?returnUrl=" + returnUrl
    )
);

‍

You might also want to disable "Self-service management" for email authenticators in the Authsignal Portal to prevent users from changing their email in the MFA UI.

‍

Wrapping Up

That's it for adding MFA to your Duende IdentityServer! You've now got a more secure login flow that requires users to prove their identity with a second factor.

You can find the complete code example referenced in this guide on GitHub.

In the next part of this series, we'll show you how to add passkey support to give your users an even smoother and more secure login experience. Stay tuned!

Question icon
Have a question?
Talk to an expert
NewsletterDemo PasskeysView docs
Duende IdentityServer
Multi-factor authentication
Guides

You might also like

The passkey UX patterns that drive adoption in 2026
Passkeys
Passkeys implementation

The passkey UX patterns that drive adoption in 2026

July 2, 2026
What is silent network authentication, and how does it work?
Silent Network Authentication
SNA

What is silent network authentication, and how does it work?

June 26, 2026
HIPAA MFA requirements and what to do before the final rule lands
Passkeys
Step up authentication
Adaptive MFA
SMS Alternative

HIPAA MFA requirements and what to do before the final rule lands

July 4, 2026

Secure your customers’ accounts today with Authsignal

Passkey demoCreate free account
Authsignal Purple Logo

Authsignal is a drop-in authentication and orchestration layer for consumer-facing businesses. Passkeys, adaptive MFA, and omnichannel verification on top of your existing identity stack. Deployed in weeks, not quarters.

AICPA SOCFido Certified
LinkedInTwitter
Platform
Drop-In Authentication
PasskeysBiometric authenticationWhatsApp OTPEmail OTPApp push authenticationPalm biometricsSMS OTPEmail OTPMagic LinksAuthenticator apps (TOTP)
View all auth methods
KEY FEATURES
No-code rules engineUser observabilityRisk-based authenticationSession managementDigital credentials APIPre-built UI
All authentication methods
Pricing
Customers
Solutions
USE CASE
Account takeovers (ATO)
Go passwordless
Call center
SMS cost optimization
Existing apps
Palm biometric payments
View all use cases
industry
Financial services
Healthcare
Marketplace
View all use cases
ROLE
Engineering
ProductCybersecurityDocs
Compare
Twilio Verify vs AuthsignalAuth0 vs AuthsignalAWS Cognito vs Authsignal + AWS Cognito
Resources
LEARN
BlogGuidesRegulatoryTemplatesDocs
COMPANY
About usWhy AuthsignalPartnersCareersSecurityContact
Integrations
Amazon Cognito
Azure AD B2C
Duende IdentityServer
Keycloak
Auth0
NextAuth.js
Custom identity provider
All integrations
United States
+1 214 974-4877
Ireland
+353 12 676529
Australia
+61 387 715 810
New Zealand
+64 275 491 983
© 2026 Authsignal - All Rights Reserved
Terms of servicePrivacy policySecuritySystem statusCookies