apereo / dotnet-cas-client

Apereo .NET CAS Client
Apache License 2.0
232 stars 176 forks source link

Too Many Redirects error #72

Closed kangweigang closed 6 years ago

kangweigang commented 7 years ago

hello: i use the .net cas client 1.1.0
project :asp.net mvc 4.0 . web.config is ok .
after login the page is "Localhost redirected too many times." can you help me ! thank you !

TheHokieCoder commented 7 years ago

@kangweigang We'd love to help! But in order to do that we need to know what settings you are using in your web.config to configure DotNetCasClient. Will you please post your casClientConfig and system.web/authentication sections so that we may see how you are currently configured? In order to protect the privacy of your servers, feel free to change your URLs to something fake like example.com.

phantomtypist commented 7 years ago

Fortunately, or unfortunately depending on how you look at it, I have too much experience with this issue :)

I will first tell you what is going on that causes this behavior to manifest. Then I will discuss a few possible underlying problems that can cause this behavior.

What's Supposed to Happen

Let's start with the obvious:

  1. You navigate to your application unauthenticated.
  2. The application redirects you to the CAS server.
  3. You authenticate with the CAS server and it a) stores your authentication information on the CAS server and b) redirects you back to your application with some authentication information.
  4. Now that you are back at your application, IIS / ASP.NET try and authenticate you. This is done by the server reaching out to the CAS server in the background to double check you are who you say you are and that you have indeed successfully authenticated with the CAS server.

This is the gist of what the normal process is for authentication.

Where It All Goes Wrong

I personally know one of two things that can cause this behavior/problem. Both could be happening for all your luck.

Root Cause 1

Your application server (or the application itself) is not communicating over the same cryptographic protocols with the CAS server in the background when it goes to retrieve the authentication info from the CAS server.

Basically, the ONLY cryptographic protocol (or Schannel) that is considered to be secure nowadays is TLS 1.2. You should be using nothing else. Well, you could still use TLS 1.1, but there are debates about that one. IMHO, just use TLS 1.2 all around and nothing else (meaning SSL 2.0, SSL 3.0, and TLS 1.0).

So a scenario where this is the case is that let's presume your systems' team is on the ball and they locked down the CAS server so it only accepts TLS 1.2 connections. This means that your application server AND the application itself both have to be capable of using TLS 1.2 (well, not just capable, but actually configured to use TLS 1.2)

So, your application server... Only Windows Server 2008 R2 and higher support TLS 1.2 at the operating system level. If you have that covered, you are good. Next, make sure that TLS 1.2 is actually turned-on on the server via some registry settings (https://technet.microsoft.com/en-us/library/dn786418(v=ws.11).aspx).

Next, your web application. By default, .NET 4.0 and 4.5.x do not turn on TLS 1.2. They will only negotiate up to TLS 1.1 by default on their own. For .NET 4.0 and 4.5.x applications you need to explicitly tell the web application to use the TLS 1.2 schannel. This is not a problem if you are targeting .NET 4.6.x or 4.7.x.

So back to your .NET 4.0/4.5.x application... Like I said, you can explicitly tell your web application to use a specific schannel by default. We want it to use TLS 1.2 by default and then fall back to lower protocols if needed. In .NET 4.5.x this is straight forward as there is an enum for this: ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;.

As for .NET 4.0, there is a bit of a catch... there is no enum available!!! No need to worry though as you can cast the enum type to a specific integer. The code you'd use is ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;. Double catch: even if your application targets .NET 4.0, you must have .NET 4.5.x installed on the actual server it runs on. The reason this works is because .NET 4.5.x layers itself on top of .NET 4.0. So when your .NET 4.0 application runs, it runs in the context of the .NET 4.5.x runtime. So when that junk of code with the enum casting gets hit at runtime, it will actually work because it's being piped through the .NET 4.5.x runtime which actually has the enum value we used in the previous paragraph.

You can read up more about this here: http://joymonscode.blogspot.com/2015/08/how-to-make-net-40-45-use-tls-12.html

Root Cause 2

Another issue I ran into in the past where this behavior was exhibited was if we had multiple CAS servers behind a load balancer (or reverse proxy) and they all didn't share the same authentication info store.

My case was that the CAS servers where configured each with their own auth store (wasn't shared). So when the client authenticated via the browser they'd hit let's say CAS server A. Now, when the web application server when to go contact the CAS server in the background it would hit CAS server B.... and B would tell the application server that the user wasn't authenticated... and thus the application server would redirect the user back to the CAS server to type in their password again. Rinse and repeat :)

If you have some knowledge about load balancers, you'd know that they can some times implement some sort of sticky session so that the same client/call goes to the same physical server behind the load balancer each time. That also contributed to this specific scenario because the client would always hit CAS server A and the web application server would always hit B.

Afterthoughts

So yeah, those are the two root causes I've run into in the past that exhibited the behavior you are seeing.

I'd suggest:

  1. If you can upgrade your application to target .NET 4.5.x (specifically I'd say 4.5.2 if you can do it.) It's not a big task and fairly straight forward. Also make sure you have .NET 4.5.2 installed on the actual web application server.
  2. Inside the application in the global.asax, inside the Application_Start method, add the schannel configuration code mentioned above to force the application to use TLS 1.2 by default.
  3. Double check with your systems' team to make sure you can rule out, or fix, root cause number 2 I mentioned above.
  4. Just to re-iterate, if you are running something older than Windows Server 2008 R2 (yes, R2), then you are out of luck and up the creek without a paddle. The operating system has to support whatever cryptographic protocol your two servers are communicating over.
  5. I'll throw this out there and say it might be the opposite: Your application server might be enforcing TLS 1.2 and your CAS server might be so old or misconfigured in that it does not support TLS 1.2.... and you'd see the same behavior.

After we figure out what your root cause of this problem is I will add a page to the Wiki about troubleshooting this problem.

phantomtypist commented 7 years ago

Any update on this @kangweigang?

johanv commented 6 years ago

I had the same problem, but it was caused by misconfiguration. I more or less blindly copied the configuration for forms authentication from the README (ok, I was smart enought to change loginUrl). But I got the eternal redirects. But it worked once I removed path="/ApplicationName/". (You probably have to adapt it to your needs, but removing it completely did the job for me.)

Sorazuu commented 6 years ago

In web.config, try to change value of ticketValidatorName from Cas20 to Cas10

vikebone commented 3 years ago

Thank you for the above. It was very helpful.

I also found another reason that this issue can be occurring. Check the .NET Authorization rules in IIS. If it is not either Anonymous or All Users it can cause this infinite redirect loop.

To check and/or change: Open IIS either at the server level or the website level. Click on IIS > Authorization Rules. Click on Allow rule. Click on right pane to Edit. Change to either All Users or All Anonymous Users. authorizationrules2

Even though the default IIS setting is for All Users note that this is not the best security policy, especially in a production environment. Many best security practices suggest to remove Anonymous and All Users access and allow only Administrators or other groups.