SAML is a protocol that is taking off more and more allowing authentication of users without passwords over public Networks. You can read way more on this in many websites. But how do we translate SAML to servers that do not understand SAML? How can we act based on information inside the SAML assertion / token (token to be called hereafter)?
Note that the info on this blog send user info to back-end servers, but you need to modify your back-end server to do something with this info!
Prerequisites
We assume you have the following in place:
- NetScaler 10.5 or later
- LB vServer with authentication enabled
- AAA-TM vServer acting as a SAML Service Provider and configured with an external IdP
- The IdP inserts attributes with info we need
Background Info / Explanation
A SAML token is issued by an Identity Provider (that’s where your user accounts resides, example: NetScaler, ADFS, Ping, etc.) after a user successfully logs in. The token is handed to the user and the user will be redirected towards the Service Provider (offering the service or application like a website). The SP will digest the token and since the SP is configured to trust the tokens issued by this particular IdP, access is allowed.
Typically NetScaler can act as the Service Provider (and as IdP, but that’s beyond the scope of this article) to allow users into the datacenter. So the SAML token allows me to pass the NetScaler and go to a particular back-end server. But how to I authenticate at this back-end server? You can use a SAML token once more, but your back-end server needs to understand SAML.
As a alternative (besides alternatives like KCD) it is possible to extract the user information (attributes) from the SAML token and use those in the policy infrastructure on NetScaler to pass on to the back-end server.
Note: NetScaler currently only extract the first value from a SAML attribute. If you have multiple values in a single attribute only the first one will be available in the PI!
Goal
We want to extract attributes from the SAML token and be able to use those in the Policy Infrastructure (PI). If we have this information in the PI we can use it to do some things like:
- Insert this information into HTTP headers
- Create cookies with this information
- Use the information in the URL
- Respond based on this info
- Content Switch based on this info
- etc.
How To
In this example we will be focussing on extracting the attribute value and inserting this into HTTP headers.
Extract the attributes
First we need to define what attributes to extract from the SAML token. This is configured on the SAML Action (SAML Server definition). The attributes can be defined with the -Attribute<x> setting. So if you want to extract an attribute called “GroupMember” you would need to use -Attribute1 GroupMember .
To add the attributes to an existing SAML Action you can use:
1 |
set authentication samlAction My_SAML_config -Attribute4 emailaddress |
An example of a complete SAML Action:
1 |
add authentication samlAction My_SAML_config -samlIdPCertName my_idp_signing_cert -samlSigningCertName my_sp_signing_cert -samlRedirectUrl "http://idp.mydomain.com/simplesaml/saml2/idp/SSOService.php" -samlRejectUnsignedAssertion OFF -samlIssuerName test3.mydomain.com -Attribute1 uid -Attribute2 GroupMember -Attribute3 Affiliatie |
This can be configured from the GUI too.
We now have the attributes from the SAML token available in the NetScaler PI. You can refer to them by using HTTP.REQ.USER.ATTRIBUTE(1) .
Use the Attributes
This is just an example, you should be able to do other things with the extracted values too. This examples inserts the values in HTTP headers when sending traffic for the connected user towards the load balancing vServer “web_srv”.
Modify the code below to represent your variables and use it at your convenience:
1 2 3 4 5 6 7 8 9 10 11 |
add rewrite action rw_act_saml_attr_1 insert_http_header SAML-Attribute-1 "HTTP.REQ.USER.ATTRIBUTE(1)" -bypassSafetyCheck YES add rewrite action rw_act_saml_attr_2 insert_http_header SAML-Attribute-2 "HTTP.REQ.USER.ATTRIBUTE(2)" -bypassSafetyCheck YES add rewrite action rw_act_saml_attr_3 insert_http_header SAML-Attribute-3 "HTTP.REQ.USER.ATTRIBUTE(3)" -bypassSafetyCheck YES add rewrite policy rw_pol_ins_saml_attr_1 true rw_act_saml_attr_1 add rewrite policy rw_pol_ins_saml_attr_2 true rw_act_saml_attr_2 add rewrite policy rw_pol_ins_saml_attr_3 true rw_act_saml_attr_3 bind lb vserver web_srv -policyName rw_pol_ins_saml_attr_1 -priority 100 -gotoPriorityExpression NEXT -type REQUEST bind lb vserver web_srv -policyName rw_pol_ins_saml_attr_2 -priority 110 -gotoPriorityExpression NEXT -type REQUEST bind lb vserver web_srv -policyName rw_pol_ins_saml_attr_3 -priority 120 -gotoPriorityExpression NEXT -type REQUEST |
Back-end
Tell your web-app to do something with this new info!
Security
Note that if you use HTTP headers for auth towards the back-end servers it might be possible for your users to send custom headers from the client through the NetScaler towards to back-end server. I would require a valid AAA session (logged-in user), but still it might be wise to create a responder policy that filters the HTTP headers you use from the internet towards the back-end server.
Check
Now you need to check if the attributes make it to your back-end server. For this you can
- Check to logs on the back-end server
Make sure that the back-end server accepts the additional customer HTTP headers, not all web servers accept non-standard HTTP headers.
Here is a PHP script that shows all headers starting with HTTP_ or SAML_ that page receives when accessed. Just create a file like headers.php and put this code in:
12345678<?phpforeach($_SERVER as $h=>$v)if(ereg('HTTP_(.+)',$h,$hp))echo "<li>$h = $v</li>\n";if(ereg('SAML_(.+)',$h,$hp))echo "<li>$h = $v</li>\n";header('Content-type: text/html');?> - Use a network trace
You can create a network trace and look into the HTTP headers. Your header should show up there:
Now even I understand it!! 🙂
I want to do exactly this. Setting up a federation between my IDP and Netscaler is proving challenging. Can we expect a “how to” on configuring Netscaler as a SAML SP?
Very good article.
I was wondering, in case the SAML2 assertion contains a email address (which is sometimes the case) and we want to forward another identifier to the applications via a header: is there any way to perform an LDAP attribute retrieval to catch, let’s say, the windows login and send it instead of the authentication principal?
That’s a use case I actually have.
Great article, but I can’t seem to get this far with NetScaler (12).
I’m using NetScaler as an SP and a remote government hosted IdP. I have successfully got the metadata exchanged and also shortened the assertion so that I can see it completely in the NetScaler aaad.debug log. The log even shows after the assertion that “canonicalize_data 0-116: saml_canon: successfully canonicalized the input data”.
My problem is that there’s probably something wrong in my saml2 action as I keep getting “Username extracted from Assertion is lengthy; Please contact your administrator.”. I have tried different urn:oid’s that are in the assertion for both the SAML action User Field and also for the Attributes without any luck.
I’ve also tried to use the Firefox SAML Tracer add-on, but that just seems to give out encrypted info so I have no idea how to debug that one.
Any ideas are more than welcome!