/
Casifying TeamDynamix (TDNext)

Casifying TeamDynamix (TDNext)

We have recently implemented TeamDynamix at our campus.  Here are my crude notes on how to accomplish authentication via CAS to TeamDynamix.

From their site:

The Only PPM Solution Designed For Higher Education.

TeamDynamixHE provides the only project and portfolio management solutions specifically tailored to accommodate the needs of Higher Education. With a simple yet powerful interface, TeamDynamixHE solutions enable colleges and universities to prioritize efforts, adapt to change, manage resources and meet commitments on time and on budget.

Notes:

  • TeamDynamix has numerous web applications, at this time version 7.1 only has SSO support for the component TDNext.
  • Since TeamDynamix uses Windows form authentication, the officail cas .Net client will not work.  So we used the method explained here: ASP.NET Forms Authentication
  • We are using .Net 4
  • Cas Server 3.4.2
  • TeamDynamix caches the authentication framework, so you will need to restart IIS for DLL changes to be loaded.

Step 1 configure TdNext's web.config to use Custom SSOAuth.

TeamDynamix has a hook for customSSO, that we must configure.

  • Configure SSOReturnUrl
  • Configure SSOLogoutUrl
  • Switch the loginurl of authentication to *LoginSSO.aspx *from Login.aspx

Note, as usual with CAS, make sure to URLEncode the service URL.

web.xml
<appSettings>
....
	<!--SSOReturnUrl: If you use a single sign on provider, set the "SSOReturnUrl" to the url for the single sign on provider.  Also, set the  <authentication> node LoginUrl to "LoginSSO.aspx"-->
	<add key="SSOReturnUrl" value="https://cas.myuniversity.edu/login?service=https%3A%2F%2Fdev-dynamix.myuniversity.edu%2FTDNext%2FLoginSSO.aspx%3FReturnUrl%3D%2FTDNext%2FHome%2FDesktop%2FDesktop.aspx" />    <!--SSOLogoutUrl: This is the url you want the users browser to go after logging out of TD.  This is required for SSO implementations and optional for others-->	<add key="SSOReturnUrl" value="https://cas.myuniversity.edu/login?service=https%3A%2F%2Fdynamix.myuniversity.edu%2FTDNext%2FLoginSSO.aspx%3FReturnUrl%3D%2FTDNext%2FHome%2FDesktop%2FDesktop.aspx" />
	<!--SSOLogoutUrl: This is the url you want the users browser to go after logging out of TD.  This is required for SSO implementations and optional for others-->
	<add key="SSOLogoutUrl" value="https://cas.myuniversity.edu/logout" />
....
</appSettings>
....
<system.web> 
....
	<authentication mode="Forms">
		<forms name="TeamDynamix" loginUrl="LoginSSO.aspx" timeout="480" defaultUrl="LoginSSO.aspx" cookieless="UseCookies" slidingExpiration="true" path="/" protection="All">
 			<credentials passwordFormat="SHA1" />
		</forms>
	</authentication>
....
</system.web>

Step 2 create the .net dll (SSOAuth that overrides the TeamDynamix interface)

  • Include the TeamDynamix SDK dll as a reference.

SSO Auth
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Routing;
using System.IO;
using System.Net;
using System.Xml;
using System.Web.Security;
using System.Net.Security;
namespace TeamDynamixCAS
{
    public class SSOAuth : TeamDynamix.AuthenticationSDK.IAuthenticationProvider
    {
        public String AuthenticationSso(System.Web.HttpRequest req)
        {
            //Set up dynamic switch for production/test
            string CASHOST = "https://dev-cas.myuniversity.edu/";
            string urlencodedService = "https%3A%2F%2Fdev-dynamix.myuniversity.edu%2FTDNext%2FLoginSSO.aspx";

            if (req.ServerVariables["HTTP_HOST"].Equals("dynamix.myuniversity.edu"))//use production cas/dynamix settings.
            {
                CASHOST = "https://cas.myuniversity.edu/";
                urlencodedService = "https%3A%2F%2Fdynamix.myuniversity.edu%2FTDNext%2FLoginSSO.aspx";
            }

            string tkt = req.QueryString["ticket"];
            if (tkt != null && tkt.Length > 0)
            {
                string service = urlencodedService + "%3FReturnUrl%3D%2FTDNext%2FHome%2FDesktop%2FDesktop.aspx";
                string validateurl = CASHOST + "serviceValidate?" + "ticket=" + tkt + "&" + "service=" + service;
                StreamReader Reader = new StreamReader(new WebClient().OpenRead(validateurl));
                string resp = Reader.ReadToEnd();
                NameTable nt = new NameTable();
                XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
                XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
                XmlTextReader reader = new XmlTextReader(resp, XmlNodeType.Element, context);
                while (reader.Read())
                {
                    if (reader.IsStartElement())
                    {
                        string tag = reader.LocalName;
                        if (tag == "user")
                            return reader.ReadString();
                    }
                }
                reader.Close();
            }
            return "";//TD expects blank, as an indicator that the user is not logged in.
        }
        public bool Authenticate(string UserName, string Password)
        {
            return false;
        }
        public bool ChangePassword(string Username, string OldPassword, string NewPassword)
        {
            return false;
        }
        public bool SupportsChangePassword { get { return false; } }
    }
}

Step 3 compile for release

  • Move the release dll to the bin directory of TDnext/bin
  • Restart IIS, since TeamDynamix caches various dlls.