question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Ticket Caching Failing With Visual Studio 2017

See original GitHub issue

The TL;DR is that when running a CAS-enabled application in Visual Studio 2017 (IIS Express), the .NET cache provider (System.Web.Caching.Cache) is immediately expiring the new service tickets as soon as they are added to the cache. Thus, no service ticket is ever able to be validated. Below is how I arrived at this conclusion.

Recently my development computer at work bit the dust, prompting me to reformat and re-install Windows 10. I took that opportunity to also upgrade to Visual Studio 2017 Enterprise (from 2015 Enterprise). When I began working on one of my CAS-enabled applications in VS2017, I immediately got the problem of a redirect cycle between my application and the CAS server.

First thing I checked was that it wasn’t another timing problem with the tolerance level for the SAML tickets, which it wasn’t. No matter what value I set for ticketTimeTolerance, the redirects still occurred. I debugged about all I could think of in my application with no indication of why the SAML ticket validation was failing and thus redirecting back to the CAS server. Even turning on the tracing per the instructions in this project’s README didn’t shine light on the source of the problem.

I finally broke down and added the DotNetCasClient project to my solution so that I could step through the code as the process was happening. Eventually I noticed that the service ticket was being added to the cache, but in a subsequent call to retrieve the ticket from the cache, null was returned. I added some code for debugging to InsertTicket(). I was able to see that, immediately after inserting the ticket into the cache the cache item count increased by one. However, after a few debugging steps, the cache count decreased by one. I read in the comments for RemoveExpiredTickets() that the cache will automatically remove any expired items, so this got me thinking that the problem was with the expiration date for the cache item being inserted. By pure luck I was able to notice that the dates for the forms authentication ticket were using UTC while the expiration date for the cache item was in local time. Furthermore, I noticed the comments for the Insert() method of System.Web.Caching.Cache recommend to always use UTC dates as issues can occur with daylight savings time. The particular problem I am having wasn’t related to DST, but on a whim I changed the insert statement from:

HttpContext.Current.Cache.Insert(GetTicketKey(casAuthenticationTicket.ServiceTicket), casAuthenticationTicket, null, expiration, Cache.NoSlidingExpiration);

to:

HttpContext.Current.Cache.Insert(GetTicketKey(casAuthenticationTicket.ServiceTicket), casAuthenticationTicket, null, expiration.ToUniversalTime(), Cache.NoSlidingExpiration);

Immediately my application worked again. To double-check that the fix was correct I have created another dummy web application that consumes CAS in Visual Studio 2017. Using the local date/time, the redirect loop occurs. Modify it to use UTC date/time, the application works as expected.

I created the same dummy application in a copy of Visual Studio 2015 I have, targeting the same version of the .NET framework (v4.5.2). Using the same configuration settings for the client in web.config, I did the same tests, except this time the caching of the service tickets works regardless of using local or UTC time for expiration. As best as I can tell, the only difference between the projects is Visual Studio 2015 versus 2017. They target the same framework version, have all the same NuGet packages/versions, and use the same web.config settings.

Using those same dummy projects (one in 2015, the other in 2017) I basically copied the code from ContainsTicket() to list the contents of the cache on each page load. Using a special query string parameter, I could instruct the page load code to add a simple string value as an object to the cache with a +1 minute expiration date. In VS2017, using the local date for expiration, the string would be gone from the cache on the next load, even though the second request was only a few seconds after adding the object to the cache. Using the UTC date, the string would stay in the cache for a minute, then be removed. Switching to VS2015 yielded the expected result that it did not matter which form of the date/time was used for expiration. The string value would stay in cache for 1 minute, then expire.

According to the MSDN Documentation for the Insert() method, the recommendation for the absoluteExpiration parameter value is for it to be a UTC date/time, not a local one. It is laughable, though, that the examples on the same page use DateTime.Now, against their own recommendation. In any case, I think it would be a good thing to change the expiration to a UTC date/time regardless of it being the absolute root cause of the problem I am experiencing.

I believe the change would need to be made at the point where the expiration date is set, which is when the forms authentication ticket is being created in CreateFormsAuthenticationTicket() of CasAuthentication.cs. The fromDate and toDate variables can be set as UTC dates, and the client has no problem in VS2017. I will create a pull request soon with the suggested changes along with documentation as to why UTC dates are needed. In the meantime, if anyone wants to weigh in on why this is happening between VS2015 (and earlier) and VS2017, it would be appreciated!

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:3
  • Comments:38 (20 by maintainers)

github_iconTop GitHub Comments

2reactions
phantomtypistcommented, Jul 19, 2017

Heads up everyone!

We now have a pre-release NuGet package feed for alpha/beta/unstable versions of the DotNetCasClient package. It can be found here: https://www.myget.org/gallery/dotnetcasclient-prerelease

Can you guys/gals please connect to the new feed and test the 1.1.0-beta0001 version of the package to see if this resolves the problem for you? Report back if you have any problems or if the issue was resolved for you.

There were some other changes in this pre-release version, those can be found in the ReleaseNotes.md file found in the release/1.1.0 branch right now.

Thanks!

@hokiecoder @danransom @webMan1 @serac @sbubaron @nicswan @scottt732 @mmoayyed

1reaction
nicswancommented, Jun 27, 2017

As a note, this issue manifested for me because .NET 4.7 was pushed as a critical update last week so was automatically added to production servers (yay!). So I imagine this will quickly become an issue for others as well. Thanks to @hokiecoder / @danransom for the fix. I was able to roll my own version and fix the issue for at least one of my apps.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Common issues and workarounds in Visual Studio setup
This article describes common issues during Visual Studio installation and provides suggested workarounds.
Read more >
Visual Studio 2017 Crash On Initial Startup After Offline ...
I created an offline install cache for Visual Studio 2017, copied that cache to another computer via an external USB drive, ...
Read more >
c# - Visual Studio user cache
Forwarding Syncfusion's answer here if anyone was wondering: As you have mentioned that you are facing the exception while using Ribbon ...
Read more >
c# - Visual Studio 2017 throws error when clicking "Quick ...
cs file and select "Quick Actions and Refactorings..." in the context menu I get an error popup which reads: The Visual Studio component...
Read more >
Can I delete the folder C:\ProgramData\Package Cache
For Visual Studio 2017, you can disable the package cache (even after Visual Studio is installed) by calling:
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found