last update: 2023/02/03
Tested with NetScaler 11, Citrix ADC 12.1 and 13.0
I needed to use a Citrix ADC (NetScaler) both, as a SAML identity provider (IDP) and service provider (SP). So I set up my test environment accordingly.
What my test environment looked like:
You see, I created two admin partitions on my Citrix NetScaler ADC, one for the service provider (SP partition), containing both, the SAML SP and a web server, and one for my identity provider (IDP partition), containing the SAML IDP.
I used these partitions to emulate “2 different Citrix NetScalers ADCs” as it does not make sense to have both, SAML-SP and SAML-IDP in the same data center (you could do conventional LDAP/RADIUS/TACACS authentication instead).
You may try using my configuration. Just surf to https://sp.josel.net. It will forward you to https://idp.josel.net (my IDP). Use test both, as username and password. You’ll then get forwarded back to the SP. I’d suggest doing your experiments using FireFox and SAML Tracer plugin (there is a similar plugin for Chrome). This will give you a good insight into SAML assertions. All Policies are displayed and discussed here.
You may download the original Citrix ADC (NetScaler) configuration for both, IDP and SP partition from here.
There is some chance for certs to be outdated as I don’t put much effort into this. The Saml IDP only does local authentication and will then forward to the SP showing content of www.norz.at.
How SAML works:
In Saml the resource (SP, Service Provider, so the website needing authentication) uses an external witness (IDP, Identity Provider) to handle user logon. They send messages called assertions.
Of course, it’s a bit hard to make sure the IDP is the desired, trustworthy, one. Same for the IDP, it’s hard to find out whether the SP requesting authentication is a trustworthy one. Trust is created using certificates.
So a user connects to a resource (SAML SP). If the user had not been authenticated before, he gets forwarded to the logon server, the so-called SAML-IDP. The SAML-IDP does the authentication.
After successful authentication, the SAML-IDP forwards the user back to the SAML-SP, also sending the so-called assertion, the prove this user was authenticated successfully. You could think of an assertion like a man’s ID card. As soon as the SAML-SP has checked the assertion, it forwards the user to the resource.
SAML-SP and resource are always located on the same Citrix NetScaler, the SAML-IDP is usually located “somewhere else on the internet”.
Certificates
SAML uses certificates to establish trust between SAML-SP and SAML-IDP.
The SAML-SP uses a server certificate to sign it’s an assertion (message) sent to the IDP. So the IDP needs to own the SP’s certificate (not its private key!). These certificates usually are private, not trusted ones.
The SAML-IDP also uses a certificate to sign (and encrypt) the assertion. This certificate (again: not the private key) has to be present on the SAML-SP, so the SAML-SP is able to decrypt and validate the assertion. Trust is established by providing the certificate. This certificate may be a self-signed one (that’s what Microsoft does with ADFS)
It’s possible to use the same certificates for both, SSL between client and SAML-IDP / SAML-SP, and to prove identity, however, I would rather use private (and therefore more trustworthy) certificates to prove identity. In my setup, I use the let’s encrypt certs for AAA-servers and self-signed ones to establish SAML trust.
In my example I use the following certificates:
SP.josel.net (my serviceprovider)
sp_signing_cert_privateKey | selfsigned | SP’s signing key. It has a private key |
idp_signing_cert | selfsigned | IDP’s signing key. No private key here! |
sp.josel.net | valid on internet (DigiCert) | SP’s SSL certificate (for HTTPS) |
idp.josel.net (my IDP)
idp_signing_cert_privateKey | selfsigned | IDP’s signing key. It has a private key |
sp_signing_cert | selfsigned | SP’s signing key. No private key here! |
idp.josel.net | valid on internet (DigiCert) | IDP’s SSL certificate (for HTTPS) |
Cirtix ADC / NetScaler as a SAML Service Provider (SAML-SP)
A Citrix ADC / NetScaler may be a SAML identity provider for any SAML service provider. Another Citrix ADC / NetScaler may be the service provider, but also services like Microsoft Azure, Microsoft Office 365, Citrix Sharefile, and many more may use a Citrix ADC as an authentication source.
In my example, I just created a simple load-balancing vServer and added authentication to it. There is nothing special about it, in fact, I used my test server (a description might be found there).
add service svc_HTTP 93.83.148.43 HTTP 80
add lb vserver lb_vsev_sp SSL 192.168.0.100 443 -AuthenticationHost idp.josel.net -Authentication ON -authnVsName SAML_SP
bind lb vserver lb_vsev_sp svc_HTTP
bind ssl vserver lb_vsev_sp -certkeyName sp.josel.net
set ssl vserver lb_vsev_sp -ssl3 DISABLED -tls13 ENABLED
Adding a pattern-set containing SAML IDPs
Following Citrix CTX316577, we should add a relay-state rule. As there can be several IDPs, I decided to create a patternset.
Navigate to Appexpert → Pattern Sets. Click Create. Add a pattern set called pat_samlIDP. Click insert and add the URL of your IDP in the form https://idp.josel.net/
. The trailing / is a must!
add policy patset pat_samlIDP
bind policy patset pat_samlIDP "https://idp.josel.net/" -index 1
The Citrix ADC / NetScaler SAML Service Provider (SP) Authentication policy
The NetScaler SAML Service provider action (SAML-SP)
GUI: Navigate to:
Security → AAA-Application Traffic → Policies → Authentication → Basic Policies → SAML
With SAML Actions click Add.
add authentication samlAction saml_sp_server -samlIdPCertName idp_signing_cert -samlSigningCertName sp_signing_cert_privateKey -samlRedirectUrl "https://idp.josel.net/saml/login" -samlUserField "Name ID" -samlIssuerName josel.net_SP -relaystateRule "AAA.LOGIN.RELAYSTATE.CONTAINS_ANY("pat_samlIDP")"
IDP Certificate Name* | SAML IDP’s certificate (we need to own it, but we don’t own it’s private key) |
Redirect URL* | The URL of the SAML IDP in use, if IDP is a NetScaler: /saml/login |
User Field | User Name in assertion, if IDP is a NetScaler this is Name ID |
Signing Certificate Name | a certificate used to sign the SAML assertion (a normal server certificate. We own a private key!) |
IDP Certificate Name | the certificate used by the IDP to sign the SAML assertion (a normal server certificate. We don’t own a private key!) |
Issuer Name | an ID for this SP. Every SP needs it’s own definition on IDP and this ID is used to match the right definition |
Relay State Rule |
a list of allowed IDPs, Citrix CTX316577 |
The Citrix ADC / NetScaler SAML Service provider policy
GUI: Navigate to:
Security → AAA-Application Traffic → Policies → Authentication → Advanced Policies → SAML
add authentication Policy SAML_SP_pol -rule true -action saml_sp_server
The SAML Service Provider (SAML-SP) Authentication vServer.
Click add
Provide name and IP (port is usually 443, the protocol is SSL and can’t be changed)
bind a server certificate (this one gets exposed to users, so it has to be trusted!)
bind the authentication policy you previously created
add authentication vserver SAML_SP SSL 0.0.0.0
set ssl vserver SAML_SP -ssl3 DISABLED -tls13 ENABLED
bind authentication vserver SAML_SP -policy SAML_SP_pol -priority 100 -gotoPriorityExpression NEXT
Authorization
Since Citrix ADC version 13, default authorization changed to deny. Because of that, access will fail. This may get fixed in two ways: Either change default authorization to allow (I can’t recommend this), or create a session policy, set authorization to allow, and bind it to the AAA vServer.
add authorization policy autho_allow true ALLOW
bind lb vserver lb_vsev_sp -policyName autho_allow -priority 100 -gotoPriorityExpression END -type REQUEST
Citrix ADC / NetScaler as a SAML Identity Provider (SAML IDP)
A Citrix ADC / NetScaler may also get used as a SAML Identity Provider (SAML-IDP). This allows authenticating to any authentication source like LDAP, RADIUS, Certificates, TACACS, local, Negotiate, O-Auth, SAML, WebAuth, EPA. In my example, I do Citrix ADC / NetScaler local authentication.
Citrix NetScaler ADC is a perfect SAML IDP, a replacement for Microsoft ADFS, both more secure and simpler, to authenticate to Azure and Office 365. There is a Blog by Manuel Wikel, both in German and English, about that subject.
Adding a pattern-set containing SAML SPs
Following Citrix CTX316577, we should add a relay-state rule. As there can be several IDPs, I decided to create a patternset.
Navigate to Appexpert → Pattern Sets. Click Create. Add a pattern set called pat_samlIDP. Click insert and add the URL of your IDP in the form https://sp.josel.net/cgi/samlauth
.
add policy patset pat_serviceProviderURLs
bind policy patset pat_serviceProviderURLs "https://sp.josel.net/cgi/samlauth" -index 1
Creating the a SAML Identity Provider Policy (SAML IDP)
Creating the SAML Identity Provider Action (Saml IDP Action) on a Citrix ADC / NetScaler
Navigate to:
Security → AAA-Application Traffic → Policies → Authentication → Advanced Policies → SAML IDP. Go to Profiles.
Click Add.
add authentication samlIdPProfile SAML_IDP_profile -samlSPCertName sp_signing_cert -samlIdPCertName idp_signing_cert_privateKey -assertionConsumerServiceURL "https://sp.josel.net/cgi/samlauth" -samlIssuerName josel.net_IDP -acsUrlRule "AAA.LOGIN.SAML_REQ_ACS_URL.EQUALS_ANY("pat_serviceProviderURLs")"
Assertion Consumer Service URL | The logon-URL of the Service provider called consumer (if it’s a Citrix ADC / NetScaler: https://FQFN/cgi/samlauth) |
Assertion Consumer Service URL Rule |
>a list of SPs, following Citrix CTX316577 |
IDP Certificate Name | The certificate used to digitally sign the assertion (a normal server certificate, we own the private key) |
SP Certificate Name | The certificate used by the service provider, so it can be trusted (IDP does not need to own the private key) |
Issuer Name | an ID of the SAML Identity Provider (this SAML IDP’s name). It would be used if SP trusts several IDPs |
Service Provider ID | an ID of the SAML Service Provider Each SAML service provider needs to have its own ID IDP profile, so there may be many profiles. This ID is used to find the right definition. (this is an optional parameter and not used in my deployment!) |
The SAML-IDP policy
add authentication samlIdPPolicy saml_IDP_Policy -rule true -action saml_idp
The authentication policy
I don’t go into authentication policies here. Just follow Citrix’s best practices, there are many guides out there. I created a policy similar to CTX113820.
add authentication Policy local_auth -rule true -action LOCAL
bind authentication vserver aaa_vsrv_test -policy local_auth -priority 100 -gotoPriorityExpression NEXT
The SAML Identity Provider (SAML-IDP) Authentication vServer.
click add
provide name, IP address, and port, usually 443 (the protocol can’t get changed)
bind a server certificate. This one gets exposed to the user, the user has to trust this certificate!
bind an authentication method and a SAML IDP policy
select both, the IDP and the authentication policy
add authentication vserver aaa_vsrv_test SSL 192.168.1.1 443
set ssl vserver aaa_vsrv_test -ssl3 DISABLED -tls13 ENABLED
bind authentication vserver aaa_vsrv_test -policy samlIdPPolicy -priority 100 -gotoPriorityExpression END
bind authentication vserver aaa_vsrv_test -policy local_auth -priority 100 -gotoPriorityExpression NEXT
Trouble shooting
I used the following tools:
Citrix NetScaler’s log (Yes, there is a log on a NetSaler, and SAML issues get logged there! You look at /var/log/ns.log)
Firefox add-on SAML-Message Decoder (also available for Chrome)
Citrix NetScaler Network traces
Issues:
I have seen several issues recently:
SAML-SP fails to forward to SAML-IDP
detected: error in the browser
check settings in SAML-SP’s SAML Authentication action: Redirect URL
SAML-IDP fails to forward to SAML-SP
detected: error in the browser
check settings on in SAML-IDP’s SAML-IDP Authentication action: Assertion Consumer Service URL
Certificate not trusted on SAML-IDP
detected: confusing message in the browser, log in IDP’s /var/log/ns.log
add SAML-SP’s signing certificate to SAML-IDP’s SAML-IDP profile: SP-Certificate Name
Exporting metadata from an SP into the IDP
Usually, in SAML, we configure just one side, export metadata, and import it to the other side. So if we configure the service provider, we can import its metadata into the IDP. That’s the way we do it if the service provider is a Citrix NetScaler ADC:
https://<servername>/metadata/samlsp/<profilename>
Clicking this link, you can import metadata from my SP into an IDP of your choice. More information can be found here. Thanks, Hermann Zauner, for this information!
I hope. that helps. Just drop me a message if you need more information. You’re very much welcome to link to my blog / my website. Thanks!
Thanks! With your post I could implement SSO between different Netscalers using SAML SP en IDP! What do you think about using an attribute for storing the password between IDP en SP? That way you can login with username and password from the IDP to the SP load balancer and than SSO tot the back-end servers.
There are a few things not correct in the pictures and the corresponding CLI lines. For example “add authentication vserver SAML_SP SSL 0.0.0.0”. The picture had 192.168.0.4 in it..
But great article.. Helped me lot!
Great to hear it was of use to you! Thanks to let me know (blogging sometimes feels like communication to /dev/NULL)
You could use an attribute to store the password in it. Sure. Problem here: Usually IDP and SP don’t really trust each other. So it’s not a technical problem but an organizational problem.
About pictures: They are in a very old state. I have to update pictures (same as command line, I now have better ones). I will do soon after my holidays, probably in May.
do you think that you will have time to update the great documentation ^
Thanks to remind me … I upgraded several times. But I didn’t upgrade the screen-shots (I hardly use GUI, so I hardly check GUI screen shots. They are still old. I’ll do it soon.
I just updated the pictures for the SAML IPD profile and SAML SP profile. I hope, it helps 🙂
I am getting the below error:SAML Assertion verification failed; Please contact your administrator
I am seeing the following errors in the ns.log:
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21175 0 : “parsing end of tag /saml:SubjectConfirmationData> ”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21176 0 : “subjectConfData end tag seen, remaining data: ></ "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21177 0 : “parsing end of tag /saml:SubjectConfirmation></sa "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21178 0 : “parsing end of tag /saml:Subject><saml:Conditions "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21179 0 : “ns_aaa_saml_parse_assertion: parsing the begg tag: Conditions NotBefore=”2019-07- ”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21180 0 : “ns_aaa_saml_parse_assertion: Parsed Conditions tag remaining data: “>https://lb.jenny.lab</saml:AudienceRestri "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21181 0 : “ns_aaa_saml_parse_assertion: parsing the begg tag: AudienceRestriction><saml:Audi "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21182 0 : “ns_aaa_saml_parse_assertion: parsing the begg tag: Audience>https://lb.jenny.lab< "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21183 0 : “SAML: ParseAssertion: Audience parsed is https://lb.jenny.lab”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21184 0 : “parsing end of tag /saml:AudienceRestriction></sa "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21185 0 : “parsing end of tag /saml:Conditions><saml:AuthnSt "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21186 0 : “ns_aaa_saml_parse_assertion: parsing the begg tag: AuthnStatement AuthnInstant=”2 ”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21187 0 : “ns_aaa_saml_parse_assertion: Parsed AuthnStatement tag remaining data: “>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProte ”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21188 0 : “ns_aaa_saml_parse_assertion: parsing the begg tag: AuthnContext><saml:AuthnContex "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21189 0 : “ns_aaa_saml_parse_assertion: parsing the begg tag: AuthnContextClassRef>urn:oasis ”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21190 0 : “parsing end of tag /saml:AuthnContextClassRef></s "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21191 0 : “parsing end of tag /saml:AuthnContext></saml:Auth "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21192 0 : “parsing end of tag /saml:AuthnStatement></saml:As "
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21193 0 : “parsing end of tag /saml:Assertion> ”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21194 0 : “assertion end tag seen, remaining data: ”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21195 0 : “SAML: Assertion is signed, trying to verify”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21196 0 : “SAML verify digest: digest algorithm SHA1, input for digest: https://idp.jenny.labjennyhttps://lb.jenny.lab<sa
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21197 0 : “SAML signature validation: algorithm is RSA-SHA1 input buffer is: eYO2zVdDWsF71LywZg5yOhbAzBM=”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21198 0 : “Error while trying to verify the signature”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21199 0 : “Verification of SAML assertion resulted in failure 917511 ”
Jul 4 15:12:58 10.110.159.137 07/04/2019:15:12:58 GMT 0-PPE-0 : default AAATM Message 21200 0 : “AAATM Error Handler: Found extended error code 917511, ReqType 16388 request /cgi/samlauth, cookie hdr “
Jennifer, it seems to be a problem about Certificates. Check if the assertion signing certificate is trusted at the other side
Getting Error
Unexpected System Error while opening the IDP . Please help how to fix the issue
Sorry, this is not enough information. Plus I’m currenty very short on time.