ADFS with EasyTerritory: On-Premises


Executive Overview:

EasyTerritory supports Active Directory Federation Services (ADFS) capability.  ADFS is a single sign on feature that enables a user to login to the EasyTerritory application through his company’s identity provider (IdP).  The IdP will authenticate the user using Active Directory credentials and direct him to EasyTerritory to access the application.

Advantages:

The advantages of leveraging ADFS with your EasyTerritory application are:

  • – Simple streamlined SSO access to your EasyTerritory application through company’s IdP portal.
  • – Strengthens security with users not needing to remember additional usernames and passwords.
  • – Ability for companies to control users’ access to EasyTerritory within their active directory.

Technical Overview:

EasyTerritory supports ADFS with the SAML (Security Assertion Markup Language) XML framework for authenticating users who are wanting to connect to EasyTerritory.

It is important to note that EasyTerritory’s SAML configuration is Ipd-Initiated, which means when a user attempts to browse to EasyTerritory they will be redirected to his company’s IdP sign-on page.

When a user is authenticated through his IdP, a token will be sent to the EasyTerritory servers. EasyTerritory will receive the token and grant access based on the credentials and authenticity of the claims in the token.

Configuration:

These configuration details are divided into two sections.  First section is the client-side configuration.  These are details that you will need in setting up ADFS on your active directory servers.  The second section is the EasyTerritory configuration that will be needed to configure SAML AuthServices on your EasyTerritory server.

Client-Side:

  • The information you will need when setting up the trust:
    •  – Relying Party’s identifiers:
      • https://apps.easyterritory.com/[Your EZT instance GUID here]/APP/
    • – SAML consumer Endpoints:
      • https://apps.easyterritory.com/[YourEasyTerritory GUID here]/APP/AuthServices/Acs
      • This uri will redirect you after you have been authenticated by your IdP.
  • An agreement on Claims:
    • EasyTerritory requires a username, first name, last name and email when authenticating claims that are sent. These claims must match on your server and EasyTerritory’s server.  You can decide what to call the claims, but those claims must be sent to an EasyTerritory administrator. Please note that there are two alternatives for userNameClaim and emailClaim.
      • Here are some examples:
        • – User Name Claim:
           http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name,http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
        • – First Name Claim:
           http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname
        • – Last Name Claim:
        • http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname
        • – Email Claim:
        • http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress,http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
  • ADFS server URI’s
    • Information an EasyTerritory administrator will need when configuring your EasyTerritory application are entity Id, the sign-on URL, and logout URL. Here are some examples.
      • – Server’s entity Id:
        • http://[Your ADFS server]/adfs/services/trust
      • – IdP sign- on URL:
        • https://[ADFS server]/adfs/ls/idpinitiatedsignon.aspx?loginToRP=[we put the EZT URL here, as we use that as OUR entity ID]
      • – Log out URL:
        • https://[ADFS server]/adfs/ls/?wa=wsignout1.0
      • We also need to know whether you need EasyTerritory to generate logout requests (and if so, whether you want them signed) or whether we can simply redirect to the bare logout URL (which is the more common scenario).
  • Certificate:
    • In order to authenticate the claims sent to EasyTerritory, EasyTerritory will need a signing certificate.
    • If your ADFS is publicly exposed we can generate a certificate from your metadata endpoint. In this case you would need to send an EasyTerritory administrator you metadata URL.  Here is an example:
      • https://[your ADFS server]/federationmetadata/2007-06/federationmetadata.xml

EasyTerritory Configuration:

Instructions on configuring SAML plugin in EasyTerritory Admin portal

  • – Please browse to your EasyTerritory site and login as an admin. Then click on the admin link on the top right corner of the page.
    • Click on the “settings” tab.

  • – Click on the “+item” button to create a new plugin.

  • – For “Name” “Assembly” “Class” “Project ID” fill in with the information above.
  • – Scrolling down on the plugin configuration make sure make to fill in the “Config” to the appropriate dropdown – OpenIntel.Plugins.SAML2Integration
  • – The first four settings represent the claims disscussed in the “Claims” section of this document.
  • – Save these settings, log out of EasyTerritory, and recycle the site application pool (for the app pool used by APP).
  • – EasyTerritory needs claims that represent the desired user name, first name, last name, and email address.
    • In general, these will come from Active Directory. Pass-through claims would only be used if the ADFS server is itself federated to other ADFS servers to permit external logins.
    • We recommend that at this point claims encryption be disabled on the ADFS side, if possible. Enable that only after verifying all other configuration.

Instructions on integrating Kentor Configuration in the APP web.config

  • Kentor AuthServices are used to provide SAML support on top of the Windows Identity model.  These are configured in the EasyTerritory website web.config file.  This section of the document also includes related web configuration that is needed.  More information about Kentor configuration is available at https://github.com/KentorIT/authservices/blob/master/doc/Configuration.md
    • On your EasyTerritory server please browse in the file explorer to:
      • Path-To-EZT/EasyTerritory/www/sites/App and open up the web.config
  • - In between the <ConfigSections> </ConfigSections> tags, paste these three sections:
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<section name="kentor.authServices" type="Kentor.AuthServices.Configuration.KentorAuthServicesSection, Kentor.AuthServices" />
  • – In between the <system.web> </system.web> tags, paste:
    <authentication mode="None" />
  • – In between the <system.serviceModel></system.serviceModel> tags, paste:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <standardEndpoints>
      <webHttpEndpoint>
        <!--
            Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
            via the attributes on the <standardEndpoint> element below
        -->
      <standardEndpoint name="" helpEnabled="false" crossDomainScriptAccessEnabled="false" maxReceivedMessageSize="30000000" />
      </webHttpEndpoint>
      <webScriptEndpoint>
         <standardEndpoint name="" crossDomainScriptAccessEnabled="false" />
      </webScriptEndpoint>
    </standardEndpoints>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

  • – In between the <modules runAllManagedModulesForAllRequests=”true”> </modules> tags and after the <add name=”URLRoutingModule”> Paste the below section:
<add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
<add name="Saml2AuthenticationModule" type="Kentor.AuthServices.HttpModule.Saml2AuthenticationModule, Kentor.AuthServices.HttpModule" />

  • – After the </system.webServer> tag paste the follow sections and make sure to edit the red text with your specific syntax, further instructions on editing in the next step:
<kentor.authServices entityId="https://ezt.yourdomain.com/APP/"    
                     returnUrl="https://ezt.yourdomain.com/APP/AuthServices/Acs"    
                     authenticateRequestSigningBehavior="Always">
       <nameIdPolicy allowCreate="true" format="Persistent" />
       <requestedAuthnContext classRef="Password" comparison="Minimum" />
  
       <identityProviders>  
            <add entityId="http://Your ADFS server/adfs/services/trust"
                 signOnUrl="https://Your ADFS server/adfs/ls/idpinitiatedsignon.aspx?loginToRP=[EZT URL here]      
                 logoutUrl="https://Your ADFS server/adfs/ls/?wa=wsignout1.0"    
                 wantAuthnRequestsSigned="true" 
                 allowUnsolicitedAuthnResponse="true"    
                 binding="HttpRedirect">
                   <signingCertificate fileName="~/App_Data/signing.cer" />
           </add>
      </identityProviders>
      <serviceCertificates>
          <add x509FindType="FindByThumbprint" 
           findValue="d1 6a 9e 6e 0d b3 82 8e d9 a8 8d 69 7e fd 5d d6 b8 bb 1a c5"  
           storeLocation="LocalMachine" 
           storeName="My"  />
      </serviceCertificates>
</kentor.authServices>

<system.identityModel>
    <identityConfiguration>
        <securityTokenHandlers>
            <securityTokenHandlerConfiguration>
                <audienceUris mode="Never">
                </audienceUris>
            </securityTokenHandlerConfiguration>
        </securityTokenHandlers>
    </identityConfiguration>
</system.identityModel>
<system.identityModel.services>
    <federationConfiguration>
        <cookieHandler requireSsl =" [false|true] " 
                       path="[root location that holds EZT and MDN services]" />
    </federationConfiguration>
</system.identityModel.services>

  • – Please make these corrections to each section in the above block:
    • kentor.authServices entityId – this should be set to the full host URI to APP/ and will be used as an identifier in the ADFS configuration.
    • returnURL – this should be set to the full host URI to APP/AuthServices/Acs which is where ADFS will POST or REDIRECT to on login.
    • add entityId – this should be set to the entity Id of the ADFS server, generally http://[ADFS server FQDN]/adfs/services/trust
    • signOnUrl – this is set to the IPD-initiated sign-on page, and passed our entity Id, generally https://[ADFS server FQDN]/adfs/ls/idpinitiatedsignon.aspx?loginToRP=[your entity Id above]
    • logoutUrl – this is set to the provider signout page, typically  https://[ADFS server FQDN]/adfs/ls/?wa=wsignout1.0″
    • bindingHttpRedirect or HttpPost depending on the ADFS endpoint choice.
    • signingCertificate – provide signing certificate. Instructions below.  Make sure to save it  in a folder that root directory of your instance (APP, DEV, TEST, or TRAIN).  In the example above the folder is named “App_Data
    • serviceCertificates – Certificates that are installed can be referenced by their “thumbprint”.
    • cookieHandler requireSsl – should be true unless the site is not using SSL.
    • path – should be to the root location with both APP and MDN (or MDNServices in an on-prem deployment) directly beneath.

Instructions on obtaining a Signing Certificate

  • – To get a key from metadata download metadata XML from
      https://ADFS server/federationmetadata/2007-06/federationmetadata.xml
  • – The XML will look like this:

  • – Copy the contents of the X509Certificate node under the ds:Signature node into a text file. The text file should look like this:
  • -----BEGIN CERTIFICATE-----(paste the X509Certificate guid here)-----END CERTIFICATE-----
  • – Make sure there is no white spaces anywhere in this text file. Save it with a .cer extension. You can reference the file directly in the web.config inbetween the <identityProviders> </identityProviders>
               <signingCertificate fileName="~/App_Data/signing.cer" />
  • – Certificates that are installed can also be referenced by their “thumbprint”.
  • – Don’t copy and paste directly from the certificate properties window, there are non-printing characters in the display that will invalidate the thumbprint.

<signingCertificate x509FindType="FindByThumbprint"

              findValue="a4 b2 4d 91 11 f3 80 62 13 83 17 ea 3f 17 86 63 65 c9 13 29"

              storeLocation="LocalMachine"

              storeName="My">

At this point, recycle the site application pool try to access EasyTerritory should redirect you to ADFS to log in, then back to the site.  If all is well, you’ll be logged in and an EasyTerritory user account created to shadow the ADFS account. 

SuperAdmin login

Note that once the SAML plugin has been added you’ll need to use the superadmin “back door” to bypass ADFS.

  • – Append “?login=sa” to the usual /APP/ URL path to get an EasyTerritory login prompt.
  • – When the SAML plugin is in use, ONLY the superadmin is allowed to log in in this way.
  • – The superadmin username and password are in the APP web.config file.
    <add key="adminUsername" value="admin" />

    <add key="adminPassword" value="77777777" />

    <add key="adminPasswordIsEncrypted" value="false" />

Troubleshooting

  • – If the claims are misconfigured, you may observe a loopback behavior between EasyTerritory and ADFS or see a message about a missing claim.
    • Note that once the SAML plugin has been added you’ll need to use the superadmin “back door” to bypass ADFS.
  • – If the expected claims aren’t found, our SAML plugin will dump all claims found to the EasyTerritory log file (settings panel in application).
    • This makes it easy to update to the correct values in the settings panel.

User Upload

Users DO NOT need to be prepopulated.  For a new unknown ADFS user, an EasyTerritory user record will be created.

  • – But users cannot be upgraded to admins until they are in Easy Territory, so you may wish to preload users who are to be admins.
  • – User Upload Security Key can be set if you want to be able to preload or remove users with the REST/Login/ExternalUser endpoint.
            public class ExternalUser
            {
                [DataMember]
                public string userName { get; set; }
                [DataMember]
                public string firstName { get; set; }
                [DataMember]
                public string lastName { get; set; }
                [DataMember]
                public string emailAddress { get; set; }
                [DataMember]
                public string loadKey { get; set; }
            }
  • – Use the PUT verb to insert a user at this endpoint, DELETE to remove one.
  • – LoadKey must match the User Upload Security Key.
  • – Delete matches on userName only.
  • – Note that deleting a user does not stop the from being recreated by a subsequent login.

Claims Encryption

Claims encryption provides an added layer of security in the event that SSL traffic is compromised by some sort of man-in-the-middle attack.

  • – An encryption certificate should be generated on the EasyTerritory server.
  • – Kentor will need both public and private keys. The certificate is referenced in the Kentor <serviceCertificates><add section noted above.
  • – The ADFS server needs only the public key.
  • – Export the certificate for use by ADFS. Only the public key is needed.  We recommend you do all other configuration first, with claims not encrypted, to simplify troubleshooting.

MapDotNet Security

The final step is to configure MapDotNet to reference EasyTerritory to verify users.  MapDotNet uses a plugin for this.  You will need to add two section references to the <configSections> element of the MDN web.config file.

  • – Note that on newer installations of EasyTerritory this may already be in place.
<configSections>
    <section name="mapdotnet.plugins" type="ISC.MapDotNetServer.Core.Plugins.PluginConfigurationSection" />
    <section name="mapdotnet.plugin.validateRESTCookies" type="MapDotNet.Plugins.ValidateRESTCookies.ValidatorConfigurationSection" />
</configSections>
  • – Copy the following to the web.config file, just before the <mapdotnet.mapservicesettings> element is as good a place as any.  Replace the text in red with the URI to your EasyTerritory /APP location.
<mapdotnet.plugins>
    <add name="RESTValidator" assembly="MapDotNet.Plugins.ValidateRESTCookies" class="MapDotNet.Plugins.ValidateRESTCookies.Validator" customConfigSection="mapdotnet.plugin.validateRESTCookies" />
</mapdotnet.plugins>
<mapdotnet.plugin.validateRESTCookies
    eztURL="URL to your EasyTerritory instance"
    cacheTTLSeconds="30"
    cacheCookie="oitoken" />

Please understand we are not ADFS administrators. We may be able to give you some support with setting up a trust, but ideally your staff will be knowledgeable about this and we will not be involved with AD Federation configuration on your end.