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.
<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.
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.