NetScaler Gateway: SAML with multiple IDPs using nFactor

Both SAML as well as nFactor are two NetScaler features that are highly underrated in my opinion. In this example I’ll share with you how I did combine them in a customer deployment to create a quite unique login experience.

  1. Background
  2. Solution
  3. Configuration
    1. Create the Second Factor (Policy Label)
    2. Create the First Factor (AAA vServer)
    3. Setup NetScaler Gateway for nFactor authentication
  4. Resulting User Experience
  5. Customizations to the Login Schema

Background

In the deployment in question I had one customer with the following requirements:

  • He’s running NetScaler Gateway along with a XenApp/XenDesktop farm
  • They wanted to provide access to a variety of different independent organizations
  • Ideally authentication should use SAML on NetScaler along with Citrix Federated Authentication Service (FAS) within XenApp/XenDesktop
  • The customer wanted to provide a single URL for all access to that service

This way each organisation that get’s on-boarded just needs to setup an ADFS server, provides the IDP certificate and could be integrated with a minor NetScaler configuration. The customers would retain authority about their user directory and users could re-use the credentials they’re familiar with.

Solution

The solution, as you might have guessed, was nFactor. After accessing the service the users are asked for their E-Mail address.

NetScaler Gateway SAML with multiple IDPs using nFactor

Based on this the user is then getting redirected to their respective organization’s IDP.

This is realized by a two-stage nFactor configuration in which the first stage gathers the username and the next factor is determined based on the E-Mail suffix provided.

Now I won’t go into every detail of how nFactor works. That will be worth an  article on it’s own. For now you could find some background in the product documentation Multi-Factor nFactor Authentication

On a high level, the configuration for the described scenario looks as follows:

NetScaler Gateway SAML with multiple IDPs using nFactor Flow Schema

 

Some points to note if you’re new to nFactor:

  • nFactor in NetScaler Gateway utilizes a AAA vServer for it’s configuration
  • The AAA server being the first factor has a “No Auth” policy bound which is always successful – we only gather input here
  • Next factor always points to an Authentication Policy Label of which you can think of like “another AAA server” as the same entities are bound here
  • The Policy Label then has a series of SAML policies bound which redirect based on the E-Mail suffix

Configuration

Ok, so how do we configure this?

First of all you’ll need your SAML authentication profiles setup. I won’t go into details about that in this article. You’ll find some information in the product documentation SAML Authentication

Create the Second Factor (Policy Label)

We’ll start this implementation from the rear end and create our SAML policies first. These will apply based on the user’s suffix and this is basically where all the magic is happening.

add authentication Policy nf-saml-select.auth.pol.saml.if-domain-a -rule "HTTP.REQ.USER.NAME.SET_TEXT_MODE(IGNORECASE).AFTER_STR("@").EQ("domain-a.local")" -action nf-saml-select.auth.act.saml.domain-a
add authentication Policy nf-saml-select.auth.pol.saml.if-domain-b -rule "HTTP.REQ.USER.NAME.SET_TEXT_MODE(IGNORECASE).AFTER_STR("@").EQ("domain-b.local")" -action nf-saml-select.auth.act.saml.domain-b

Next we’ll need to create a “empty” Login Schema for the SAML authentication. Why empty? Because SAML doesn’t need a schema on NetScaler since the IDP is performing the authentication.

add authentication loginSchema nf-saml-select.auth.schema.noschema -authenticationSchema noschema
add authentication loginSchemaPolicy nf-saml-select.auth.schema.noschema.true -rule true -action nf-saml-select.auth.schema.noschema

Finally we can create a Policy Label combining the SAML policies with the Login Schema

add authentication policylabel nf-saml-select.auth.pol.label.select-next -loginSchema nf-saml-select.auth.schema.noschema.true
bind authentication policylabel nf-saml-select.auth.pol.label.select-next -policyName nf-saml-select.auth.pol.saml.if-domain-a -priority 100 -gotoPriorityExpression END
bind authentication policylabel nf-saml-select.auth.pol.label.select-next -policyName nf-saml-select.auth.pol.saml.if-domain-b -priority 110 -gotoPriorityExpression END

This concludes the second factor which could now be used as a next factor for the first factor.

 

Create the First Factor (AAA vServer)

First of all we’d need an Authentication Server to work with and bind an appropriate certificate. The server does not need to be addressable so you can just enter an empty IP address.

add authentication vserver nf-saml-select.aaa.vs.int SSL 0.0.0.0
bind ssl vserver nf-saml-select.aaa.vs.int -certkeyName wildcard.nerdscaler.lab

Next you’ll need the Authentication Policy which will be of type NO_AUTHN. This results in the first factor always being successful since we’re only gathering information. The actual authentication is completely up to the second factor.

add authentication Policy nf-saml-select.auth.pol.noauth -rule true -action NO_AUTHN

As a last piece we’ll also need another Login Schema. This time we’ll use the OnlyUsername.xml that is shipped with the NetScaler to start with

add authentication loginSchema nf-saml-select.auth.schema.onlyuser -authenticationSchema "/nsconfig/loginschema/LoginSchema/OnlyUsername.xml"
add authentication loginSchemaPolicy nf-saml-select.auth.schema.onlyuser.true -rule true -action nf-saml-select.auth.schema.onlyuser

Finally we can bind everything to our Authentication Server and – most important – point to the previously created Policy Label as a Next Factor.

bind authentication vserver nf-saml-select.aaa.vs.int -policy nf-saml-select.auth.schema.onlyuser.true -priority 100 -gotoPriorityExpression END
bind authentication vserver nf-saml-select.aaa.vs.int -policy nf-saml-select.auth.pol.noauth -priority 100 -nextFactor nf-saml-select.auth.pol.label.select-next -gotoPriorityExpression NEXT

This concludes the nFactor authentication itself.

Setup NetScaler Gateway for nFactor authentication

Finally we need to configure our NetScaler Gateway to point to the AAA vServer for authentication. This is done creating and setting a Authentication Profile.

add authentication authnProfile nf-saml-select.auth.prof -authnVsName nf-saml-select.aaa.vs.int
set vpn vserver nf-saml-select.ngw.vs.ssl.443 -authnProfile nf-saml-select.auth.prof

This leaves you with the following…

Resulting User Experience

If the user logs in with a user from Domain-A…

NetScaler Gateway: SAML with multiple IDPs using nFactor - Domain-A Login

…he gets redirect to Domain-A’s IDP.

NetScaler Gateway: SAML with multiple IDPs using nFactor - Domain-A IDP

If the user logs in with a user from Domain-B…

NetScaler Gateway: SAML with multiple IDPs using nFactor - Domain-B Login

…he gets redirect to Domain-B’s IDP.

NetScaler Gateway: SAML with multiple IDPs using nFactor - Domain-A IDP

If a user logs in with a non-configured Domain he’ll receive a error message:

NetScaler Gateway: SAML with multiple IDPs using nFactor Unknown Domain Error

Customizations to the Login Schema

One of the great features of nFactor is the fact that you can finally fully customize your login form. So if you actually want to ask for an E-Mail instead of a UPN you can simply copy and customize one of the Login Schemas in /nsconfig/loginschema/LoginSchema/

Based on the OnlyUsername.xml I’ve created the following OnlyEmail.xml for example:

<?xml version="1.0" encoding="UTF-8"?>
<AuthenticateResponse xmlns="http://citrix.com/authentication/response/1">
<Status>success</Status>
<Result>more-info</Result>
<StateContext></StateContext>
<AuthenticationRequirements>
<PostBack>/nf/auth/doAuthentication.do</PostBack>
<CancelPostBack>/nf/auth/doLogoff.do</CancelPostBack>
<CancelButtonText>Cancel</CancelButtonText>
<Requirements>
<Requirement><Credential><ID>login</ID><SaveID>ExplicitForms-Username</SaveID><Type>username</Type></Credential><Label><Text>E-Mail</Text><Type>plain</Type></Label><Input><AssistiveText>Please supply E-Mail</AssistiveText><Text><Secret>false</Secret><ReadOnly>false</ReadOnly><InitialValue></InitialValue><Constraint>.+</Constraint></Text></Input></Requirement>
<Requirement><Credential><Type>none</Type></Credential><Label><Text> Please enter E-Mail ...</Text><Type>confirmation</Type></Label><Input /></Requirement>
<Requirement><Credential><ID>saveCredentials</ID><Type>savecredentials</Type></Credential><Label><Text>Remember my password</Text><Type>plain</Type></Label><Input><CheckBox><InitialValue>false</InitialValue></CheckBox></Input></Requirement>
<Requirement><Credential><ID>loginBtn</ID><Type>none</Type></Credential><Label><Type>none</Type></Label><Input><Button>Log On</Button></Input></Requirement>
</Requirements>
</AuthenticationRequirements>
</AuthenticateResponse>

Which results in the following login form

NetScaler Gateway SAML with multiple IDPs using nFactor

 

10 Replies to “NetScaler Gateway: SAML with multiple IDPs using nFactor”

  1. Thank you for sharing this information. This is a bit over my head at the moment, and I’m trying to learn and implement this, and you’ve documented it well enough that I *THINK* I understand whats happening! I have a question regarding the following line —

    add authentication policylabel nf-saml-select.auth.pol.label.select-next -loginSchema nf-saml-select.auth.schema.noschema.true

    Since we’re specifying a loginschema, shouldn’t it be named “nf-saml-select.auth.schema.noschema” (no .true at the end, since .true is actually a loginschemapolicy)?

    Like

    1. Hi Joe, thanks for the feedback and glad you find it useful! I think you might be right! Sadly I dont have my PoC running anymore so I hope I’ll manage to test this again some day to (potentially) correct the article.

      Like

  2. I’m having some problems getting this to work right. I’m never prompted for the username, it just moves forward to my SAML authentication (which fails, but I believe that is unrelated). I don’t ever get the OnlyUser.xml to display.

    Any tips?

    Like

    1. Hi Joe, I’ve actually seen this happening before in some newer versions of NetScaler – but I don’t know if it’s fixed in the latest version. Are you using the latest build?

      However, there is a workaround!
      Apparently it seems that NetScaler doesn’t display Factors with only NO_AUTHN policies anymore – why? I don’t know.
      So what you can do is add any second, lower (higher number) priority, policy. For example a LOCAL one. Just as a dummy.
      This will make the factor to be displayed again. However, this second dummy policy will never match due to the lower priority.
      That worked for me in one scenario where the above config failed after an update.

      You mind sharing your firmware and result – if successful?
      I’d then include a note in the article.

      Thanks!

      Like

      1. I actually got around this and was coming here to update you. I’m currently on 12.0 56.20.

        I found CTX226488 that detailed the creation of a noauth policy. It says to use “http.req.url.contains(“/nf/auth/doAuthentication.do”)” as the rule instead of True. Sure enough, it works every time now!

        Now I just have to figure out how to get my SAML actions set right. I’m getting errors from azure telling me that request property Subject is not supported. So much fun! :)

        Thanks again for the notes on getting this setup!!

        Like

      2. Nice! I wasn’t aware of that one. Probably a cleaner solution than the dummy-policy. Thanks for sharing!
        You’re welcome! I’m happy to get more people hooked on playing around with the mighty nFactor :-)

        Like

  3. This is a great article that fits exactly a scenario that we are trying to work through. However, we are having an issue federating with AzureAD as the IDP. After the Netscaler captures the username, it inserts it as the subject in the SAML request. AzureAD apparently does not support subject in SAML requests, despite documentation indicating that it would just ignore it. If I authenticate without capturing the user name first, the request is sent without a subject and authentication is successful.

    I realize that this is a Microsoft problem, but I thought I might have better luck fixing it on the Netscaler than getting Microsoft to change. Any ideas?

    Like

    1. Hi Wes, I’m not sure but the first – and only – thing that comes to my mind is traffic policies.
      The NS forwarding credentials seems like a default behavior that might be hard/impossible to change.

      Two things come to my mind – just wild guesses though
      – in nFactor schemas when you drop down the “advance options” (or something similar) I think you can set username and password fields – maybe you can work with that
      – in traffic policies you can actually tweak what is used for a SSO – it might be a very remote guess but maybe that can be used to be applied in this case as well (https://netscalerrocks.com/netscaler/flexible-sso-in-build-10-5-56-12/ has some indication on what I mean)

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.