apereo / dotnet-cas-client

Apereo .NET CAS Client
Apache License 2.0
234 stars 172 forks source link

Null ProxyGrantingTicket found #119

Closed AnupPatilDassaultSystem closed 1 day ago

AnupPatilDassaultSystem commented 3 years ago

Error is random and not reproducible. There are CAS logs created. What test should be performed to check for error before calling GetProxyTicketIdFor method
casTicket = CasAuthentication.ServiceTicketManager.GetTicket(formsAuthTicket.UserData); if (casTicket.ProxyGrantingTicket == null) { // How to get PGT?? // } Current workaround restart IIS website on the production server. Production is using a load balancer and a single front-end server. There is no cache enabled on the Server side. IIS application pool recycles every 20 minutes. Test Url - https://help.3ds.com/MyAppTest.aspx Using another My Apps Service within the company to get data by proxy authentication. Using CAS authentication URL: https://eu1-ds-iam.3dexperience.3ds.com/3DPassport/my-profile My Apps Service to get data using PGT - https://eu1-apps.3dexperience.3ds.com/enovia/resources/AppsMngt/apps/appsForUser Error Output - CAS Is Authenticated: True CAS Ticket: ST-850625-7cwPxvNTgts9coel3kZb-cas CAS Ticket Details: [ST-850625-7cwPxvNTgts9coel3kZb-cas] NetID............. vch Proxy............. PGT IOU......... PGT............. Proxy Tickets... Origin Service.... https://betahelp.3ds.com/MyAppTest.aspx Client Address.... 10.16.8.16 Valid From........ 2/15/2021 9:08:58 AM Valid Until....... 2/15/2021 9:38:58 AM Assertion......... Principal....... vch Valid From...... 2/15/2021 9:08:58 AM Valid Until..... 1/1/0001 12:00:00 AM Attributes...... Proxy Ticket Error: System.InvalidOperationException: Unable to obtain CAS Proxy Ticket. at DotNetCasClient.CasAuthentication.LogAndThrowOperationException(String message) at DotNetCasClient.CasAuthentication.GetProxyTicketIdFor(String targetServiceUrl) at SolidWorks.Content.SWHelp.MyAppTest.Page_Load(Object sender, EventArgs e) in C:\lc\src_ds\SWHelp\MyAppTest.aspx.cs:line 202 Good Output - CAS Is Authenticated: True CAS Ticket: ST-5333856-349PFWBoGyMsFKeLO4RQ-cas CAS Ticket Details: [ST-5333856-349PFWBoGyMsFKeLO4RQ-cas] NetID............. vch Proxy............. PGT IOU......... TGT-5922734-luHmcKgrqUZObhoNLEcBAcXCT70BOh6pIXnPWZl0rhaeY7T6ew-cas PGT............. PGTIOU-661059-7ChLanrXDqlOlwfOQ7vp-cas Proxy Tickets... Origin Service.... https://help.3ds.com/HelpProductsDS.aspx Client Address.... 10.16.3.169 Valid From........ 7/14/2021 10:25:51 PM Valid Until....... 7/14/2021 10:55:51 PM Assertion......... Principal....... vch Valid From...... 7/14/2021 10:25:51 PM Valid Until..... 1/1/0001 12:00:00 AM Attributes...... Proxy Ticket from GetProxyTicketIdFor received: ST-5426807-0oYXKgxxxIJ0Sh9cmuIB-cas

Error is due to ProxyGrantingTicketId being null. proxyGrantingTicketId cannot be null After the exception, the problem is not being able to recover after doing CasAuthentication.ClearAuthCookie(). The only way to recover is doing an IIS reset. The code works but after getting this exception not able to recover even after doing the ClearAuthCookie().

              if (iCnt > 3)
                {
                    // CasAuthentication Clearing Auth Cookie after three Refresh tries.
                    CasAuthentication.ClearAuthCookie();
                    if ((HttpContext.Current != null) && (HttpContext.Current.Session != null))
                    {
                        HttpContext.Current.Session.Clear();
                        HttpContext.Current.Session.Abandon();
                    }

                }

This is from Memory dump during error on production – We have reviewed the dumps, please find the analysis below – This is what we’ve been seeing. The exception we are looking for seems to be on this memory dump: w3wpDSHelpPID8156Date02_19_2021Time_04_59_43PM398First Chance System.ArgumentException.dmp In this stack we are having the exception: 0:029> kc

Call Site

00 KERNELBASE!RaiseException 01 clr!RaiseTheExceptionInternalOnly 02 clr!IL_Throw 03 DotNetCasClient!DotNetCasClient.Utils.UrlUtil.ConstructProxyTicketRequestUrl 04 DotNetCasClient!DotNetCasClient.CasAuthentication.GetProxyTicketIdFor 05 SWHelp!SolidWorks.Content.SWHelp.MyAppTest.Page_Load 06 System_Web_ni!System.Web.UI.Control.OnLoad 07 System_Web_ni!System.Web.UI.Control.d246.MoveNext 08 System_Web_ni!System.Web.Hosting.ApplicationManager.SuspendAllApplications 09 System_Web_ni!System.Web.UI.Control.LoadRecursiveAsync 0a System_Web_ni!System.Web.UI.Page.d523.MoveNext 0b System_Web_ni!System.Web.Hosting.ApplicationManager.SuspendAllApplications 0c System_Web_ni!System.Web.UI.Page.ProcessRequestMainAsync 0d System_Web_ni!System.Web.UI.Page.d515.MoveNext 0e System_Web_ni!System.Web.Hosting.ApplicationManager.SuspendAllApplications 0f System_Web_ni!System.Web.UI.Page.ProcessRequestAsync 10 System_Web_ni!System.Web.UI.Page.<>cDisplayClass554_0.b0 11 System_Web_ni!System.Web.HttpContext.InvokeCancellableCallback 12 System_Web_ni!System.Web.UI.Page.d554.MoveNext 13 System_Web_ni!System.Web.Hosting.ApplicationManager.SuspendAllApplications 14 System_Web_ni!System.Web.UI.Page.ProcessRequestAsync 15 System_Web_ni!System.Web.TaskAsyncHelper.BeginTask 16 App_Web_pbgxtqie!ASP.myapptest_aspx.BeginProcessRequest … 0:029> !pe2 Address: 0x00000079d3dbd960 HResult: 0x80070057 Type: System.ArgumentException Message: For proxy ticket requests, proxyGrantingTicketId cannot be null and must be specified. Stack Trace: SP IP Function Source

If we review the code, the exception is being thrown as the object is null public static string ConstructProxyTicketRequestUrl( string proxyGrantingTicketId, string targetService) { CasAuthentication.Initialize(); if (string.IsNullOrEmpty(proxyGrantingTicketId)) throw new ArgumentException("For proxy ticket requests, proxyGrantingTicketId cannot be null and must be specified."); if (string.IsNullOrEmpty(targetService)) throw new ArgumentException("For proxy ticket requests, targetService cannot be null and must be specified.");

That is being passed as a parameter on this method:

public static string GetProxyTicketIdFor(string targetServiceUrl)
{
  CommonUtils.AssertNotNullOrEmpty(targetServiceUrl, "targetServiceUrl parameter cannot be null or empty.");
  if (CasAuthentication.ServiceTicketManager == null)
    CasAuthentication.LogAndThrowConfigurationException("Proxy authentication requires a ServiceTicketManager");
  FormsAuthenticationTicket authenticationTicket = CasAuthentication.GetFormsAuthenticationTicket();
  if (authenticationTicket == null)
    CasAuthentication.LogAndThrowOperationException("The request is not authenticated (does not have a CAS Service or Proxy ticket).");
  if (string.IsNullOrEmpty(authenticationTicket.UserData))
    CasAuthentication.LogAndThrowOperationException("The request does not have a CAS Service Ticket.");
  CasAuthenticationTicket ticket = CasAuthentication.ServiceTicketManager.GetTicket(authenticationTicket.UserData);
  if (ticket == null)
    CasAuthentication.LogAndThrowOperationException("The request does not have a valid CAS Service Ticket.");
  string responseXml = (string) null;
  try
  {
    responseXml = HttpUtil.PerformHttpGet(UrlUtil.ConstructProxyTicketRequestUrl(ticket.ProxyGrantingTicket, targetServiceUrl), true)

0:029> !do2 0000007ad8fd4368 0x0000007ad8fd4368 DotNetCasClient.CasAuthenticationTicket 0008 NetId : 0000007ad8fd18f8 "vch" [3] (System.String) 0010 ServiceTicket : 0000007ad8f7a658 "ST-1713038-t4saojRRdfuziqjT1nCh-cas" [35] (System.String) 0018 ProxyGrantingTicketIou : 0000007ad8fd2678 "PGTIOU-997576-HuIaIFJ4ceczwidxbQmf-cas" [38] (System.String) 0020 ProxyGrantingTicket : NULL 0028 Proxies : 0000007ad8fd43c8 (System.Collections.Generic.List) [Length: 0] 0030 OriginatingServiceName : 0000007ad8fd42d8 https://help.3ds.com/MyAppTest.aspx [35] (System.String) 0038 ClientHostAddress : 0000007ad8fd4338 "10.16.8.83" [10] (System.String) 0040 Assertion : 0000007ad8fd2700 (DotNetCasClient.Security.Assertion) 0048 ValidFromDate : 0000007ad8fd43b0 19/02/2021 17:59:43 (System.DateTime) 0050 ValidUntilDate : 0000007ad8fd43b8 19/02/2021 18:29:43 (System.DateTime)

pbhenson commented 1 day ago

Nobody has responded to this issue and it seems no commits have been made for 5 years? Is this project abandoned?

In any case, we ran into this problem, and it turns out not to be an issue with the cas client but rather the underlying .NET framework:

https://stackoverflow.com/questions/7422859/memorycache-empty-returns-null-after-being-set

It was fixed in .NET 4.5 and also evidentally backported to .NET 4 but only available by request? Our application is using .NET 4.6, but the latest precompiled cas client binary available uses .NET 2. I'm not sure how .NET works with components using mixed framework versions, but we're going to try to compile our own cas client library using .NET 4.6 and see if the problem goes away.

Stack Overflow
MemoryCache Empty : Returns null after being set
I have a problem with an MVC 3 application that is using the new .NET 4 System.Runtime.Caching MemoryCache. I notice that after a seemingly unpredictable time, it stops caching stuff, and acts like...
phantomtypist commented 1 day ago

I am glad you were able to do some debugging/troubleshooting and able to figure out what the problem was.

I'm not sure what precombiled binaries you are using, but you should be using NuGet packages. The latest NuGet package for this project supports both .NET 2, 3.5 and 4.x. So if you add the NuGet package into a project that targets 4.x, then NuGet will select the binary compiled for .NET 4.x

phantomtypist commented 1 day ago

https://www.nuget.org/packages/DotNetCasClient/

DotNetCasClient 1.3.2
.NET client for the Apereo Central Authentication Service (CAS)
pbhenson commented 1 day ago

Thanks for the info. I'm playing the role of the idp admin here :), so I don't know all the details of what our windows web developers are up to. I looked at that nuget page and just saw the ".NET Framework 2.0" label at the top, but I see now if I click on the "Frameworks" tab below there are newer versions listed.

phantomtypist commented 1 day ago

@pbhenson ah yeah, that is confusing. Microsoft and their geniuses at naming things. That first "tag" really means it's part of the .NET Standard 2.0 "collection". At some point years ago they started to group and classify multiple actual framework version together that have "compatibility".

If you care to dig into that rabbit hole look here: https://learn.microsoft.com/en-us/dotnet/standard/frameworks

Target frameworks in SDK-style projects - .NET
Learn about target frameworks for .NET apps and libraries.
pbhenson commented 1 day ago

I try to avoid Windows rabbit holes as much as possible :), but our Windows devs were stalled on sorting this out so I was digging through the .NET code trying to track down the issue.

If I understand the nuget page now, it's "compatible" with a wide range of versions from 2.0 through 4.8.1, but only provides precompiled binaries for 2.0, 3.5, 4.0, and 4.5? Our local app is using 4.6 something as I understand. I've got no idea how they pulled in this dependency though.

One way or the other, either they're using an old buggy version of the framework, or a newer version has a regression and is exhibiting the same problem. Not my issue or this module's issue at this point; hopefully they'll sort things out.

Thanks again...

phantomtypist commented 1 day ago

@pbhenson a 4.5 assembly should work in a 4.6 application. Somehow communication to them they should be using NuGet to install package/binary dependencies. Using the NuGet Package Manager built into Visual Studio, they should be able to download this specific page named "DotNetCasClient" and when the package manager installs the package it will load and reference the correct 4.5 assembly into the project.

There are a few copy cat CAS clients out there for the traditional .NET Framework (pre "core" and pre v5) so maybe they downloaded (manually) or installed someone else's unofficial version. It could also be that they downloaded on of the very old "releases" from the Releases tab on this GitHub project. Definitely have them try and start over using the NuGet route.

I know several places that are using the most recent (1.3.2) nuget package version in .NET projects targeting 4.7.2 and 4.8.x.

If possible, try and convince them to upgrade the entire project and all dependent projects to 4.8. That 4.6 they are targeting is well out of support IIRC.