Contact salesSign inSign up
AuthsignalAuthsignal
Product
Passwordless / multi-factor authentication (MFA)
Drop-in authentication
Risk-based authentication
Passkeys
Biometric authentication
WhatsApp OTP
Authenticator apps (TOTP)
Push authentication
SMS OTP
Email OTP
Magic links
See all authenticators
See less authenticators
Palm biometrics
Contactless payments & identity verification
Flexible integration modes
Pre-built UI
Low code
UI components
Customizable
Custom UI
Flexible
Digital credentials API Beta
Authenticate customers instantly using digital credentials
Session management
Keep users signed in across web and mobile after authentication
Fraud Controls
Rules and policies engine
Step-up authentication
No-code rule creation
Risk alerts
User observability
Audit trails
Dynamic linking
Why Authsignal?
Complete authentication infrastructure from enrollment to step-up auth, modular by design
Solutions
By USE CASE
View All
Account takeovers (ATO)
Go passwordless
Call center
SMS cost optimization
Existing apps
QR code payments
Step-up MFA
Palm biometrics payments
By INDUSTRY
View All
Financial services
Marketplace
e-Commerce
FinTech
Crypto
Healthcare
By Integration (identity provider)
Amazon Cognito
Azure AD B2C
Duende IdentityServer
Keycloak
Auth0
NextAuth.js
Custom identity provider
By ROLe
Engineers
Product
Passwordless / Multi-factor Authentication (MFA)
Flexible Integration Modes
Pre-built UI · Low code
UI Components · Customizable
Custom UI · Flexible
Digital credentials API Beta
Authenticate customers instantly using digital credentials
Session management
Issue JWT access and refresh tokens
Why Authsignal?
Plug in Authsignal to elevate your IDP — effortless integration with any architecture.
Drop-in Authentication
Risk-based authentication
Passkeys
Biometric authentication
WhatsApp OTP
SMS OTP
Email OTP
Magic links
Authenticator apps (TOTP)
Push notifications
Palm Biometrics
Contactless payments & identity verification
Fraud Controls
Rules and Policies Engine
Step-up Authentication
No Code Rule Creation
Risk Alerts
User Observability
Audit Trails
Use Cases
Financial services
Account takeovers (ATO)
Marketplace
Go passwordless
e-Commerce
Solutions
By Use Case
Account takeovers (ATO)
Go passwordless
Call center
SMS cost optimization
Existing apps
QR code payments
Step-up MFA
Palm Biometric Payments
View all Use Cases
By Industry
Financial services
Marketplace
e-Commerce
FinTech
Crypto
Healthcare
View all Industries
By Integration (identity provider)
Amazon Cognito
Azure AD B2C
Duende IdentityServer
Keycloak
Auth0
NextAuth.js
Custom identity provider
By Role
Engineers
PricingAboutDocsBlog
Schedule a call
Try Authsignal
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
Step up authentication
Adaptive MFA
Guides

Step-up authentication with Duende IdentityServer and Authsignal

Morgan French-Stagg
⬤
December 1, 2025
Share
Step-up Auth with Duende IdentityServer and Authsignal

Step-up authentication adds an extra layer of security when users try to access sensitive resources or perform high-risk actions. Instead of requiring strong authentication for every login, you can prompt users for additional verification only when they're doing something that requires it, like accessing financial data or changing account settings.

This approach strikes a balance between security and user experience. Users can browse freely with basic authentication, but when they attempt sensitive operations, they'll need to verify their identity with MFA.

In this guide, we will look into how to add step-up authentication to Duende IdentityServer using Authsignal. You will learn how to trigger additional authentication challenges based on rules you define, such as requiring MFA for specific applications or when users haven't authenticated with MFA yet in their current session.

This guide builds on our previous blog demonstrating Authsignal MFA with Duende IdentityServer: (https://www.authsignal.com/blog/articles/how-to-add-mfa-to-duende-identityserver-with-authsignal)

‍

Set up

First, follow the instructions in the Identity Server Demo Github Repository:https://github.com/authsignal/identity-server-example.

This will set up two applications:

  • IdentityServer itself
  • A demo client

‍

How it works

The StepUpInteractionResponseGenerator intercepts the authorization process at a critical point. After the user has logged in but before granting access to the requested application, it calls Authsignal's track API with context about the request.

Authsignal's rules engine evaluates this context against your configured rules. If step-up authentication is required, it returns the challenge URL. The generator then redirects the user to Authsignal's prebuilt UI to complete MFA.

Once the user completes the challenge, Authsignal redirects them back with a token. The generator validates this token before allowing the authorization code flow to continue. If validation fails, the request is denied.

‍

Implementation

Starting with the base IdentityServer example, we add a new class that decorates AuthorizeInteractionResponseGenerator with our step-up authentication logic:

using Authsignal;
using Duende.IdentityServer.Configuration;
using Duende.IdentityServer.Extensions;
using Duende.IdentityServer.ResponseHandling;
using Duende.IdentityServer.Services;
using Duende.IdentityServer.Validation;
using IdentityModel;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http.Extensions;

public class StepUpInteractionResponseGenerator(
	IdentityServerOptions options,
	ISystemClock clock,
	ILogger<AuthorizeInteractionResponseGenerator> logger,
	IConsentService consent,
	IProfileService profile,
	IAuthsignalClient authsignal,
	IHttpContextAccessor httpContextAccessor)
	: AuthorizeInteractionResponseGenerator(options, clock, logger, consent, profile)
{
	protected override async Task<InteractionResponse> ProcessLoginAsync(ValidatedAuthorizeRequest request)
	{
		var result = await base.ProcessLoginAsync(request);

		if (!result.IsLogin && !result.IsError)
		{
			// handle redirect back from authsignal
			var token = request.Raw.Get("token")?.ToString();
			if (token != null)
			{
				var validateChallengeRequest = new ValidateChallengeRequest(token);
				var validateChallengeResponse = await authsignal.ValidateChallenge(validateChallengeRequest);
				if (validateChallengeResponse.State == UserActionState.CHALLENGE_SUCCEEDED)
				{
					return result;
				}
				else
				{
					logger.LogWarning("Challenge failed: {State}", validateChallengeResponse.State);
					result.Error = OidcConstants.AuthorizeErrors.UnmetAuthenticationRequirements;
				}
			}

			var trackRequest = new TrackRequest(
				UserId: request.Subject.Identity.GetSubjectId()!,
				Action: "identity-server-authorize",
				Attributes: new TrackAttributes(
					Username: request.Subject.Claims.First(c => c.Type == JwtClaimTypes.Name)?.Value,
					RedirectUrl: httpContextAccessor.HttpContext?.Request.GetDisplayUrl(),
					IpAddress: httpContextAccessor.HttpContext?.Connection.RemoteIpAddress?.ToString(),
					UserAgent: httpContextAccessor.HttpContext?.Request.Headers["User-Agent"].ToString(),
					DeviceId: httpContextAccessor.HttpContext?.Request.Cookies["__as_aid"]?.ToString(),
					Custom: new Dictionary<string, string> {
						{ "client_id", request.Client.ClientId },
						{ "amr", string.Join(",", request.Subject.Identity.GetAuthenticationMethods()?.Select(c => c.Value)) }
					}
				)
			);

			var trackResponse = await authsignal.Track(trackRequest);

			if (trackResponse.State == UserActionState.CHALLENGE_REQUIRED)
			{
				result.RedirectUrl = trackResponse.Url;
			}
		}

		return result;
	}
}

‍

Next, inject our new IAuthorizeInteractionResponseGenerator in the ConfigureServices method in

HostingExtensions.cs :

public static WebApplication ConfigureServices(this WebApplicationBuilder builder)
{
 // [...]

	builder.Services.AddHttpContextAccessor();
	builder.Services.AddTransient<Duende.IdentityServer.ResponseHandling.IAuthorizeInteractionResponseGenerator, StepUpInteractionResponseGenerator>();
	
	return builder.Build()
}

‍

After making these changes, start IdentityServer:

cd src/IdentityServer
dotnet run

‍

Additionally, start the WebClient:

cd src/WebClient
dotnet run

‍

Navigate to https://localhost:5002 .

You will then be prompted to log in to IdentityServer (username: alice , password: alice).

If configured in the Authsignal rules engine, you may be requested to perform step-up authentication.

‍

Example step-up scenarios

Step up for specific applications

In our example we pass the client_id value from the Authorization Code Request in the track call. This allows rules to be created that only require a step-up for specific client applications.

‍

Step up if the user hasn’t completed MFA yet

In our example we pass along the amr claim from the session cookie in the track call. This allows us to define rules based on the presence of this claim, ensuring that a user isn’t required to use MFA until they attempt to access a sensitive application.

This can provide a good balance between security and usability.

‍

Wrapping up

Step-up authentication gives you fine-grained control when users need to prove their identity with MFA. By integrating Authsignal with Duende IdentityServer, you can enforce adaptive security without disrupting the user experience for low-risk activities.

You can find the complete example code in the IdentityServer demo repository. For more information about configuring rules and using Authsignal, checkout Authsignal docs, or connect with our team.

Question icon
Have a question?
Talk to an expert
NewsletterDemo PasskeysView docs
Duende IdentityServer
Step up authentication
Adaptive MFA
Guides

You might also like

Authsignal joins IATA Strategic Partnership Program to advance digital identity adoption in travel and aviation
Partnerships
Airlines

Authsignal joins IATA Strategic Partnership Program to advance digital identity adoption in travel and aviation

April 10, 2026
How to add push authentication to your app with Authsignal and React Native
Push authentication
React native
Node.js
Multi-factor authentication
Guides

How to add push authentication to your app with Authsignal and React Native

March 27, 2026
BSP Circular 1213: Philippine banks must replace SMS OTPs by June 2026
BSP Circular 1213
Philippine banking
SMS OTP
Risk based authentication

BSP Circular 1213: Philippine banks must replace SMS OTPs by June 2026

March 18, 2026

Secure your customers’ accounts today with Authsignal

Passkey demoCreate free account

Authsignal delivers passwordless and multi-factor authentication as a service. Focused on powering mid-market and enterprise businesses to rapidly deploy optimized good customer flows that enable a flexible and risk-based approach to authentication.

AICPA SOCFido Certified
LinkedInTwitter
Passwordless / multi-factor authentication (MFA)
Pre-built UI (low code)UI components (customizable)Custom UI (flexible)
Why Authsignal?
Drop-in authentication
Risk-based authentication PasskeysBiometric authenticationWhatsApp OTPSMS OTPEmail OTPMagic linksAuthenticator apps (TOTP)Push authenticationPalm biometricsDigital Credential Verification API
Rules and policies engine
User observability
Industries
Financial services
Marketplace
e-Commerce
FinTech
Crypto
View all industries
Teams
Engineers
Use cases
Account takeovers (ATO)
Go passwordless
Call center
SMS cost optimization
Existing apps
View all use cases
Identity providers (IDPs)
Amazon Cognito
Auth0
Azure AD B2C
Custom identity provider
Duende IdentityServer
Keycloak
NextAuth.js
Integrations
ASP.NET
C#
Java
Node.js
Open ID Connect (OIDC)
PHP
Python
React
Ruby
Ruby on Rails
Compare
Twilio Verify vs AuthsignalAuth0 vs AuthsignalAWS Cognito vs Authsignal + AWS Cognito
Resources
BlogDeveloper docsFree Figma mobile passkeys templateFree Figma desktop passkeys templateFree Figma webapp passkeys template
Company
About usWhy AuthsignalCareersPress releasesPartnersContact us
What is
SMS OTP
Risk Based Authentication
IP Spoofing
Passwordless authentication
Multi-Factor Authentication (MFA)
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