Flexible Multi-Factor flows in Citrix ADC (NetScaler) using Azure MFA


Multifactor Authentication in Citrix ADC / NetScaler

I came across following issue, doing a Citrix ADC / NetScaler project:

My customer wanted to use Azure MFA for internal users and LDAP/RADIUS for external users like contractors and parters.

That’s a typical use-case for n-factor authentication. So how do we solve problems like that?

The solution

A Solution based on group membership

The difference between internal and external users is group membership. In case of my customer, all external users had been member of the group “Contractors”, while internal users are not.

So the first step is, to find out, whether this user is member of this group. To do so, we have to ask for the user-name (an e-mail address, …), to identify that user. Next, we have to search the directory, in my case Azure AD for this user, to get the group membership. Authentication can not be done yet, as we don’t know how to authenticate!

As soon as we know the group, this user belongs to, we are able to decide.

Internal users get forwarded to Azure MFA to do the authentication. Azure MFA is just a SAML IDP. TThis would normally be out of our scope, and would be abslutely no problem, if this would not be a Microsoft product. In a perfect world, we would just create a SAML-SP policy, that’s it. However, life is not a walk in the park. So I also had to write some words about problems with Azure IDP.

External users, instead of using Azure MFA, get normal 2 factor authentication.

Ask the user

An other way would be: Create a drop-down list and ask the user. My customer didn’t like this approach, so I went with the first method. But it would not change the solution very much.

The n-factor flow

There is a (somewhat) new feature called n-factor flows. On a long term, it is intended to supersede traditional n-factor. It’s built on n-factor, so traditional n-factor will stay, but I would guggest using n-factor flow, if you are new to multi factor. It’s way more user-friendly than traditional n-factor. We don’t have to deal with policy labels and things like that. So I decided to do it using n-factor flows. And to be honest, I’ll do n-factor that way in future, as it’s a huge step forward.

I don’t have Azure MFA, so my lab is a bit different about the last factor.

A multi-factor login can contain several types of objects:

  • Authentication factors (with user input required)
  • Decision Blocks (not visible to users, they add the logic of the flow)
  • EULA Blocks, showing text to users (are technically the same as authentication factors)
  • Drop down lists (are technically the same as authentication factors)

Creating a first factor

We have to navigate to SecuritAAA – Application TrafficnFactor VisualizernFactor Flows.

Click Add. This will add an (almost) empty flow. There is just a first factor, and it’s currently empty.

Creating a Citrix ADC / NetScaler n-factor flow 1We have to click the plus sign to define this factor.

Creating a Citrix ADC / NetScaler n-factor flow 2Give this factor a name (Comment is optional) and click Create.

Creating a Citrix ADC / NetScaler n-factor flow 3We now have named our factor and have to add a Schema and one or more policies.

What a Schema is good for

A Schema defines the lay out of a login dialogue. Citrix ADC / NetScaler currently (version 13.0 47.22) has 30 built in templates.

Creating the Schema

Click the light blue row labelled with “Add Schema“. In the dialogue “Choose Login Schema” click Add.

Creating a Citrix ADC / NetScaler n-factor flow 4Creating a Citrix ADC / NetScaler n-factor flow 5Give it a name and then click the little pen next to noschema

Creating a Citrix ADC / NetScaler n-factor flow 6Click on LoginSchema to select a Schema of your choice. In this case, I select the OnlyUserName schema.

Creating a Citrix ADC / NetScaler n-factor flow 7Select the schema. You may edit the schema, by clicking edit on the right top corner. You may edit this schema for several languages.


It’s absolutely important to click Select prior to clicking Create! Failing to click select will lead to using the noschema template. Login dialogues will therefore fail.

Creating a Citrix ADC / NetScaler n-factor flow 8Double-check if you see the right template here. If not, click the little pen and repeat from here. Click Create if you see the right template.

Your schema is created. Double-check if it’s selected and click OK in “Choose Login Schema“.

Creating a Citrix ADC / NetScaler n-factor flow 10We now see the schema. Let’s create the policy.

The authentication policy

I assume, you know LDAP on Citrix ADC / NetScaler. If not, I suggest reading this article.

A plain text LDAP authentication process consists of 7 packets (for security reasons we don’t use plain text any more, so there are additional packets to set up the SSL session, but I dont mention these here, they are not relevant right here):

  1. First, LDAP logs in the so called Administrator Bind DN. The administrator bind DN is a service user, it is used to look up target user object (the user, we actually want to log on).
  2. The LDAP server replies with a success message.
  3. A search for the user, we want to log on. This packet does not contain a password.
  4. A search result for this search, containing the user-name in LDAP syntax (cn=Johannes.Norz,ou=LocalUsers,ou=DomainUsers,dc=training,dc=lab would be the name of a user called Johannes.Norz, located in training.lab domain’s OU DomainUsers and sub-OU LocalUsers). It also contains attributes like group-names, mail-address, last-login time-stamp and some more.
  5. the attempt to log on this user (containing the password).
  6. a success or fail message.
  7. logging off the administrator bind DN.

I explained this flow in detail here.

In this case, we don’t have a password, so we have to skip steps 5 and 6. This is done by un-checking the Authentication check-box in the Authentication LDAP Server profile. All the rest looks like a regular LDAP policy. Take care to select the correct Server Logon Name Attribute (SamAccountName if you prefer a name in NetBIOS sysntax like Johannes.Norz, or UserPrincipalName if you like a UPN like Johannes.Norz@training.lab. You could also use any other attribute like the phonenumber or the e-mail address (mail), however, these attribute are not required to be unique all over Active Directory

The LDAP policy

NetScaler: LDAP-Serverdefinition for group-extraction only (Non authentication policy)The policy will use the non-authenticating server-definition described above. The Expression will be a simple true value.

We will bind this policy to our first factor.

Creating a Citrix ADC / NetScaler n-factor flow 11In this case, we don’t need to add additional policies (you would have to do so, if you have several domains. In this case, it makes sense to put the fastest domains with the most users in it on top, the slowest domains on the bottom.

We have to click the green plus sign to add a next factor. This next factor is a Decision Block.

Decision Blocks

These are non-authenticating factors. Their point is to do a decision, and that’s what we have to do right now: We know about user-name and group membership. We have to decide, how to carry on.

Creating a Citrix ADC / NetScaler n-factor flow 12Select Create Decision block

Creating a Citrix ADC / NetScaler n-factor flow 13We now see, our first factor got a second factor bound to it. It’s orange, meaning, it’s a decision block. Decision blocks never have a schema (as decision blocks are not visible to users).

We have to click Add Policy to be able to do a decision.Creating a Citrix ADC / NetScaler n-factor flow 14Click add, or select a policy.

Creating a Citrix ADC / NetScaler n-factor flow 15The type of policy has to be NO_AUTH, and the policy expression AAA.USER.IS_MEMBER_OF("group-name"). In case we have several groups, I’d strongly suggest using AAA.USER.IS_MEMBER_OF_ANY("Pattern-Set-name"). Using pattern-sets significantly reduces memory consumption and CPU overhead.

Creating a Citrix ADC / NetScaler n-factor flow 16All the next factors will be similar: Link and create a factor, bind a schema and add policies. The user-name does not have to be entered twice, instead, it’s passed from factor to factor.


If you want to sign on to applications seamlessly, Citrix ADC / NetScaler n-factor will always use the last factor for single sign on (SSO). Because of this, LDAP will usually have to be the last factor.

What’s odd about Azure IDP

Our first try will very likely just fail. Azure will tell us, it doesn’t like the “subject attribute” to be in the request. “Azure AD doesn’t support specifying a subject for a request and will return an error if one is provided”, as Microsoft says.

The subject in SAML is the user-name. That’s the name, our user just specified. This is bad news for us, as we just asked for the user-name, and Azure will ask for this user-name again. Users will complain, but no help here, it’s by design, it’s Microsoft.

But how to overcome this issue? I found a solution at Leee Jeffries blog. We just have to type the following command into the (BSD!) shell, to make it working:
Azure MFA, Dont's send a subject in a SAML authentication requestnsapimgr_wr.sh -ys call=ns_saml_dont_send_subject

This, however, won’t survive a reboot, so we have to make it persistent. Please read this blog, how to do it!


There are some things that maybe could go wrong.

  • The first login dialogue is empty (no username/password field, just an empty page).
    In this case, you didn’t define a correct schema, or you forgot to click select while creating the schema. Go here.
  • The factor does not complete successfully (seems like the user gad not been found, but the user-name is correct)
    In this case, you didn’t define a correct schema, or you forgot to click select while creating the schema. Go here.
  • Users are pissed due to too many dialogues
    Your flow uses too many pages. Try to reduce!

About the author

Johannes Norz

Johannes Norz is a Citrix Certified Citrix Technology Advocate (CTA), Citrix Certified Instructor (CCI) and Citrix Certified Expert on Application Delivery and Security (CCE-AppDS).

He frequently works for Citrix international Consulting Services and several education centres all around the globe.

Johannes lives in Austria. He had been borne in Innsbruck, a small city (150.000 inhabitants) in the middle of the most beautiful Austrian mountains (https://www.youtube.com/watch?v=UvdF145Lf2I)

Add comment

By Johannes Norz

Recent Posts

Recent Comments