How to Configure NetScaler as SAML Service Provider and Shibboleth as SAML Identity Provider

How to Configure NetScaler as SAML Service Provider and Shibboleth as SAML Identity Provider

book

Article ID: CTX200271

calendar_today

Updated On:

Description

The following are the steps to configure NetScaler as SAML service provider and Shibboleth as SAML identity provider:

  1. Shibboleth configuration

  2. NetScaler configuration

  3. Sample SAML request and response

  4. Troubleshooting Shibboleth

  5. Troubleshooting NetScaler

In the following configuration section, assume that NetScaler AAA-TM is configured:

  • nssp.example.com resolves to FQDN of TM vserver.

  • aaavs.example.com resolves to FQDN of AAA vserver.

  • idp.wi.int resolves to FQDN of Shibboleth IDP server.
    Note: Shibboleth is configured for user authentication against LDAP server "1.1.1.1" and domain "example.com".

1. Shibboleth configuration

Shibboleth version: 2.3.3

Assuming that a working version of Shibboleth is running in the environment.

The following changes pertains to NetScaler as SAML service provider and Shibboleth as LDAP authentication provider. For information about Shibboleth configuration, see Shibboleth documentation.

In a successfully installed Shibboleth IDP, there are multiple directories:

[root@idp shibboleth-idp]# ls
bin  conf  credentials  lib  logs  metadata  temp  war

Configure Shibboleth IDP for LDAP authentication

  1. Edit /conf/login.conf and configure LDAP server as follows:

    ShibUserPassAuth {
    edu.vt.middleware.ldap.jaas.LdapLoginModule required
          host="1.1.1.1"
          port="389"
          baseDn="cn=users,dc=example,dc=com"
          bindDn="Administrator@example.com"
          bindCredential="Password"
          ssl="false"
          userFilter="sAMAccountName={0}";
    
     };

    Here LDAP authentication occurs against "1.1.1.1:389" and user has to authenticate with sAMAccountName.

  2. Create a data connector in attribute-resolver.xml for LDAP authentication.

    The following configuration specifies the LDAP server for user authentication and the attributes to extract after user authentication.

         <resolver:DataConnector id="myLDAP" xsi:type="dc:LDAPDirectory"
            ldapURL="ldap://1.1.1.1"
            baseDN="cn=users,dc=example,dc=com"
            principal="Administrator@example.com"
            principalCredential="Password">
            <dc:FilterTemplate>
                <![CDATA[
                    (cn=$requestContext.principalName)
                ]]>
            </dc:FilterTemplate>
            <dc:ReturnAttributes>userPrincipalName sAMAccountName </dc:ReturnAttributes>
         </resolver:DataConnector>

    Open attribute-resolver.xml to define the return attributes. In attribute-resolver.xml, you can see multiple attribute definitions. Copy one of the definitions and modify it for userPrinicpalName and sAMAccountName.

    In the following example, attribute definition is listed for UserPrincipalName. Remember that SourceAttributeID should match with the LDAP return attribute and dependency should match with the LDAP connector ID. Multiple attribute encoders can be specified, in the following example it shows SAML2string.

    <resolver:AttributeDefinition xsi:type="ad:Simple" id="userPrincipalName" sourceAttributeID="userPrincipalName">
            <resolver:Dependency ref="myLDAP" />
            <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="userPrincipalName"/>
        </resolver:AttributeDefinition>
    
    <resolver:AttributeDefinition xsi:type="ad:Simple" id="sAMAccountName" sourceAttributeID="sAMAccountName">
            <resolver:Dependency ref="myLDAP" />
            <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="sAMAccountName"/>
        </resolver:AttributeDefinition>

    Alternate method

    Attribute encoder can be specified with nameFormat and Friendlyname as follows:

    <resolver:AttributeEncoder xsi:type="enc:SAML1StringNameIdentifier" nameFormat="urn:mace:shibboleth:1.0:nameIdentifier name="urn:mace:dir:attribute-def:eduPersonTargetedID friendlyName="NameIdentifier"/>
    <resolver:AttributeEncoder xsi:type="enc:SAML2StringNameID" nameFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
    />
  3. Filter the defined attribute to anyone. Edit attribute-filter.xml and add the following lines:

    <afp:AttributeFilterPolicy id="userPrincipalName">
    <afp:PolicyRequirementRule xsi:type="basic:ANY"/>
    <afp:AttributeRule attributeID="userPrincipalName">
    <afp:PermitValueRule xsi:type="basic:ANY"/>
    </afp:AttributeRule>
    </afp:AttributeFilterPolicy>

    Here "basic:ANY" means that the value can be provided to anyone (no restriction applied). Remember, the attributeID should match with what is defined in attribute-resolver.xml.

  4. Perform a test to check if the attribute is extracted after user authentication. Run the following command from /opt/shibboleth-idp/bin/, and you can notice that UserprincipalName is returned. Ensure that principal points to a useraccount in the LDAP.

    [root@idp bin]#  ./aacli.sh --configDir=/opt/shibboleth-idp/conf --principal=user1
    
    <?xml version="1.0" encoding="UTF-8"?><saml2:AttributeStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
       <saml2:Attribute Name="userPrincipalName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
          <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">User1@example.com </saml2:AttributeValue>
       </saml2:Attribute>
       <saml2:Attribute Name="sAMAccountName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
          <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">User1</saml2:AttributeValue>
       </saml2:Attribute>
    </saml2:AttributeStatement>
    
  5. To configure a metadata file for NetScaler, use the following example of nssp.example.com and modify it accordingly for your deployment. (The fields highlighted in Yellow should be replaced with hostname of TM vserver). Assume the location of the file is "/opt/shibboleth-idp/metadata/nssp-example-metadata.xml".

    This file should be placed in a remote location where IDP can access it. In this case it is placed in NetScaler at "/netscaler/ns_gui/vpn", so it can be accessed from AAA vserver. It is not mandatory to keep the file on NetScaler.

    <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_724200788f8391f96053f72adc628fecc808d09a" entityID="nssp.example.com">
    
       <md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:1.0:protocol">
        <md:Extensions>
          <init:RequestInitiator xmlns:init="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Binding="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Location="https://nssp.example.com/Shibboleth.sso/Login"/>
          <idpdisc:DiscoveryResponse xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="https://nssp.example.com/Shibboleth.sso/Login" index="1"/>
          <init:RequestInitiator xmlns:init="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Binding="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Location="https://nssp.example.com/Shibboleth.sso/Login"/>
        </md:Extensions>
        <md:KeyDescriptor>
          <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:KeyName>nssp.example.com</ds:KeyName>
            <ds:X509Data>
    
    <ds:X509SubjectName>CN=nssp.example.com</ds:X509SubjectName>
              <ds:X509Certificate>
    X509 Certificate (Netscaler Signing Certificate nssp-example.cer)
    </ds:X509Certificate>
            </ds:X509Data>
          </ds:KeyInfo>
        </md:KeyDescriptor>
        <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://nssp.example.com/cgi/samlauth" index="0"/>
     </md:SPSSODescriptor>
     
    </md:EntityDescriptor>
  6. Configure the metadata location in relaying-party.xml (/opt/shibboleth-idp/conf). Edit relaying-party.xml and add a relaying party with id: nssp.example.com. Fields highlighted in Yellow specifies which part of the assertion to be signed, NetScaler supports signature verification for both. (signResponses and signAssertions can be set to "always").

    If the signature validation fails, then set it to "never" to temporarily disable signing.

    <rp:RelyingParty id="nssp.example.com”                                provider="nssp.example.com"                               defaultAuthenticationMethod="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" defaultSigningCredentialRef="IdPCredential" >
    
    <rp:ProfileConfiguration xsi:type="saml:ShibbolethSSOProfile" includeAttributeStatement="false" assertionLifetime="PT5M" signResponses="conditional" signAssertions="never"/>
            <rp:ProfileConfiguration xsi:type="saml:SAML2SSOProfile" includeAttributeStatement="true" assertionLifetime="PT5M" assertionProxyCount="0" signResponses="always" signAssertions="never" encryptAssertions="never" encryptNameIds="never"/>
            <rp:ProfileConfiguration xsi:type="saml:SAML2AttributeQueryProfile" />
            <rp:ProfileConfiguration xsi:type="saml:SAML2ArtifactResolutionProfile" />
    
      </rp:RelyingParty>
    

    Create a MetadataProvider ID for NetScaler and point to the metadata file created in step 5.

    <metadata:MetadataProvider id="URLMDNS" xsi:type="metadata:FileBackedHTTPMetadataProvider" xmlns="urn:mace:shibboleth:2.0:metadata"
                              metadataURL="https://aaavs.example.com/vpn/nssp-example-metadata.xml"
                              backingFile="/opt/shibboleth-idp/metadata/nssp-example-metadata.xml">
                <metadata:MetadataFilter xsi:type="metadata:ChainingFilter">
                        <metadata:MetadataFilter xsi:type="metadata:EntityRoleWhiteList">
                        <metadata:RetainedRole>samlmd:SPSSODescriptor</metadata:RetainedRole>
                    </metadata:MetadataFilter>
                </metadata:MetadataFilter>
            </metadata:MetadataProvider>
        </metadata:MetadataProvider>

2. NetScaler configuration

The following section covers, how to configure SAML on NetScaler.

  1. Create a SAML action on the NetScaler, to extract UserPrincipalName from the SAML response.

    1. Create a CertKey for NetScaler (nssp-example-key). Provide the same certificate as nssp-example-metadata.xml and private key associated with that certificate.

      add ssl certKey nssp-cert -cert nssp-example.cer -key nssp-example-key
    2. Create a CertKey with Shibboleth signing certificate (idp-cert-key). IDP certificate is accessible from the IDP-METADATA file - https://idp.example.com/idp/profile/Metadata/SAML.

      add ssl certKey idp.wi.int -cert "/nsconfig/ssl/idp-cert.cer"
    3. Create a SAML action with redirect URL and point to the IDP and SP signing certificates created in the preceding step.

    SAML Redirect URL: https://idp.wi.int/idp/profile/SAML2/POST/SSO
    SAML IDP CertName: idp-cert-key
    SAML SP CertName: nssp-example-key

    > add authentication samlAction shibboleth -samlIdPCertName idp-cert-key -samlSigningCertName nssp-example-key -samlRedirectUrl "https://idp.wi.int/idp/profile/SAML2/POST/SSO" -samlUserField userPrincipalName -samlIssuerName nssp.example.com
  2. Create SAML policy.

    > add authentication samlPolicy shibboleth ns_true shibboleth
  3. Bind SAML policy to AAA vserver. Certificate bound to NetScaler vserver is independent of SAML certificate.

    > add authentication vserver av1 SSL 10.10.10.2 443
    > bind ssl vs av1 –certkey <NS_Certificate>
    > bind authentication vserver av1 -policy shibboleth
  4. Create load balanced vserver and set authentication to AAA vserver.

    > add lb vserver lb1 SSL 10.10.10.1 443 -persistenceType NONE -cltTimeout 180 -AuthenticationHost aaavs.example.com -Authentication ON -authnVsName av1
    > bind lb vserver lb1 service_s1
    > bind ssl vserver lb1 –certkey <NS_Certificate>

3. Sample SAML request and response

SAMLRequest generated by NetScaler:
(Verify the highlighted fields in Yellow for troubleshooting.)

<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://nssp.example.com/cgi/samlauth" Destination="https://idp.example.com/idp/profile/SAML2/POST/SSO" ID="_64330a8ef3900a7fa8cedb1271b2ebe5" IssueInstant="2014-09-23T00:55:49Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">nssp.example.com</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod><ds:Reference URI="#_64330a8ef3900a7fa8cedb1271b2ebe5"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod><ds:DigestValue>Digest_Value</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>Signature_Valuue</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>
Netscaler_Signing_Certificate (nssp-example.cer, refer to section: 2.1.a) </ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></samlp:AuthnRequest>

SAMLResponse generated by Shibboleth:
(Verify the highlighted fields in Yellow for troubleshooting.)

<?xml version="1.0" encoding="UTF-8"?><saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://nssp.example.com/cgi/samlauth" ID="_8682a26aecd596e4952b0d2b9a661d6c" InResponseTo="_64330a8ef3900a7fa8cedb1271b2ebe5" IssueInstant="2014-09-23T01:00:14.081Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">nssp.example.com</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#_8682a26aecd596e4952b0d2b9a661d6c"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>Digest_Value</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>Signature_Value</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>IDP_Certificate (idp-cert.cer, refer to section:2.1.b)
</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml2p:Status><saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></saml2p:Status><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_57a1b6c685fcae6314ff8a9f41052680" IssueInstant="2014-09-23T01:00:14.081Z" Version="2.0"><saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">nssp.example.com</saml2:Issuer><saml2:Subject><saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" NameQualifier="nssp.example.com">_4a5af6cba683cd020f4f484171647d72</saml2:NameID><saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml2:SubjectConfirmationData Address="10.217.28.34" InResponseTo="_64330a8ef3900a7fa8cedb1271b2ebe5" NotOnOrAfter="2014-09-23T01:05:14.081Z" Recipient="https://nssp.example.com/cgi/samlauth"/></saml2:SubjectConfirmation></saml2:Subject><saml2:Conditions NotBefore="2014-09-23T01:00:14.081Z" NotOnOrAfter="2014-09-23T01:05:14.081Z"><saml2:AudienceRestriction><saml2:Audience>nssp.example.com</saml2:Audience></saml2:AudienceRestriction></saml2:Conditions><saml2:AuthnStatement AuthnInstant="2014-09-23T01:00:14.068Z" SessionIndex="3c8492dd7e244b7497d8b0142535f028d6f52ae29621bb36d957f4fda706771b"><saml2:SubjectLocality Address="10.217.28.34"/><saml2:AuthnContext><saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef></saml2:AuthnContext></saml2:AuthnStatement><saml2:AttributeStatement><saml2:Attribute Name="userPrincipalName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">User1@example.com</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="sAMAccountName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">User1</saml2:AttributeValue></saml2:Attribute></saml2:AttributeStatement></saml2:Assertion></saml2p:Response> 

Verify if NetScaler creates AAA session for user "user1@example.com", after successful authentication.

4. Troubleshooting Shibboleth

Complete the following steps to troubleshoot Shibboleth:

  1. Check idp-access.log.

    tail -f /opt/shibboleth-idp/logs/idp-process.log
  2. Restart the Apache service, after making changes to the Shibboleth config.

    #/var/lib/apache-tomcat-6.0.33/bin/startup.sh
    #/var/lib/apache-tomcat-6.0.33/bin/shutdown.sh

5. Troubleshooting NetScaler

Complete the following steps to troubleshoot NetScaler:
  1. Enable syslogparams to loglevel all and use /var/log/ns.log for more debug information.

    > set syslogparams –loglevel all
    # tail -f /var/log/ns.log
  2. Check nsconmsg counters.

    # nsconmsg -d statswt0 -g saml

    For information about the error counters, see CTX200177 - Configuration and Troubleshooting for NetScaler as SAML IDP and Siteminder as SAML SP.

 

Environment

The above mentioned sample code is provided to you as is with no representations, warranties or conditions of any kind. You may use, modify and distribute it at your own risk. CITRIX DISCLAIMS ALL WARRANTIES WHATSOEVER, EXPRESS, IMPLIED, WRITTEN, ORAL OR STATUTORY, INCLUDING WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NONINFRINGEMENT. Without limiting the generality of the foregoing, you acknowledge and agree that (a) the sample code may exhibit errors, design flaws or other problems, possibly resulting in loss of data or damage to property; (b) it may not be possible to make the sample code fully functional; and (c) Citrix may, without notice or liability to you, cease to make available the current version and/or any future versions of the sample code. In no event should the code be used to support ultra-hazardous activities, including but not limited to life support or blasting activities. NEITHER CITRIX NOR ITS AFFILIATES OR AGENTS WILL BE LIABLE, UNDER BREACH OF CONTRACT OR ANY OTHER THEORY OF LIABILITY, FOR ANY DAMAGES WHATSOEVER ARISING FROM USE OF THE SAMPLE CODE, INCLUDING WITHOUT LIMITATION DIRECT, SPECIAL, INCIDENTAL, PUNITIVE, CONSEQUENTIAL OR OTHER DAMAGES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Although the copyright in the code belongs to Citrix, any distribution of the sample code should include only your own standard copyright attribution, and not that of Citrix. You agree to indemnify and defend Citrix against any and all claims arising from your use, modification or distribution of the sample code.

Issue/Introduction

The following article describes how to configure NetScaler as SAML service provider and Shibboleth as SAML identity provider.