Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

This error can also occur when two Shibboleth VMs exist behind a load balancing front end, but the front end has not been configured to route subsequent requests for the same session (based on the "JSESSIONID" parameter) to the same VM. Then one VM sends the Browser to CAS, but the response gets routed to the other VM.

SP Initiated

At one point I thought that it would be possible to run an SP Initiated test case to a Sandbox Shibboleth running on the local desktop or through an SSH tunnel to a VM in the machine room.

However, the only proven solution is to install code on the Pre-Production Shibboleth VM and then put an entry in the hosts file to point the "authIn an SP Initiated login, the user goes to the application first and is then sent back to CAS. For example, if you go to "http://mail.bulldogs.yale.edu" name to the IP address of the Pre-Production VIP on the F5.

The rest of this section will describe the problem with all other mechanisms.

The IdP Initiated test was simplified because the code that handles the "Unsolicited/SSO" URL does not do any checks on the network address. Technically, the "Unsolicited/SSO" is a Shibboleth programming convention and not part of the SAML standard, so checks are not required.

However, if you go to the Service Provider and press a "Login from Yale" button or select Yale from a pulldown list of universities, then the SAML Request object generated by the Service Provider and the protocol by which it is sent to Shibboleth are part of the SAML standard, and that standard requires Shibboleth to do some extra checks that make the network configuration a bit more complicated.

Furthermore, while the network path from the Browser to the Service Provider (to send the Shibboleth Response) is just normal Yale networking and is not changed by the Shibboleth testing configuration, the SAML message that the SP sends to the Browser and then expects the Browser to deliver to Shib obviously is going to be affected by which Shib VM you want to use and how the Browser sends data to it.

Shibboleth processes the SAML Request first, before it even sends you to CAS in order to login. The Request has to go through a series of checks:

...

get your mail, then the Google Apps login through Shibboleth is SP Initiated. Other examples include yale.box.com, yale.service-now.com, and www.yale.edu/iptv.

The Service Provider generates a SAML Request message and sends it to Shibboleth. Unfortunately, the SP knows that Yale's Shibboleth server is located at "https://auth.yale.edu/idp/

...

.." and not only does it tell the Browser to

...

Now we get to the last test, which is harder and requires a longer description. The SAML protocol requires a Request to include the URL to which the Request is sent to also be data in an internal XML field of the Request, and it requires the IdP to check that this field is correct. Depending on whether the Request is sent as a POST or a Redirect, the URL for PROD Shib will be "https://auth.yale.edu/idp/profile/SAML2/POST/SSO" or "https://auth.yale.edu/idp/profile/SAML2/Redirect/SSO".

Of course, this URL will also have been included in the HTTP headers, and previously some mechanism was used to rewrite or reroute the HTTP flow to the test Shibboleth. That did not change the XML content. So now the problem is to ensure that the URL that the test Shibboleth server receives matches a URL that it reconstructs using the Host header and the HTTPServletRequest object it receives.

Of course, with open source you can download and read the Java code to see exactly how it is done. You can even find the Spring Bean statement that configures the comparison and replace it with new code that relaxes the rules. However, generally speaking if the Host header contains go to that network address, but it also includes this URL in the Request message. Shibboleth implements the requirement in the SAML standard that it must determine its own network URL and compare that string with the network URL sent in the SAML Request, and reject the SAML Request if the two don't match.

The problem here is that you cannot configure Shibboleth with a fixed URL string and tell it to use that string in the comparison. Instead, Shibboleth calculates its own URL using information in the HTTP headers, and information provided by Tomcat in the HTTPServletRequest object.

Of course, this is not a problem for Production Shibboleth because that machine really is "https://auth.yale.edu" and Tomcat believes that the message arrived over SSL (at least as far as the proxy) then the comparison will work. So you will have a problem when you are trying to handle an SP Initiated Login and either:

...

. The problem then is to try and trick a test version of Shibboleth running on another network address into believing that it really is on a host named "auth.yale.edu"

...

If the URL in the XML and the URL that Shibboleth generates don't match, Shibboleth writes an error message to the log containing the two strings it is comparing. You know you have to fix your client configuration when one of the two strings reported in the log containsand the request is coming in over SSL/TLS (https), on port 443, even if that is not the case.

If you don't get it right, then Shibboleth discards the Request, generates a error message in the log, and displays an error page. The log message will always say that it was comparing "https://auth.yale.edu/idp/..." to its own network address and the comparison did not match. Looking at the string it was trying to match, you will see what it generated:

  • "http://localhost:8080/" -  You have both problems, Redirector has rewritten the Host header and you have a tunnel to 8080.gave the Browser the local address and it passed this information on to Shibboleth
  • "http://auth.yale.edu" - The host header is rightYou generated the right hostname, but Tomcat doesn't think this is https.has told Shibboleth this request came in on "http" instead of "https"
  • "https://auth.yale.edu:8080" - Tomcat knows this is httpsis willing to say the request was "https", but the host header had a port number inserted.

...

  • real port number got reported

At one point I thought this problem was solvable. I now realize it is not worth the effort. Do all your basic testing using IdP Initiated URLs. Any final end-to-end testing, where you start with an SP URL and end with an actual login to you Eliapps mailbox or you Box files should be done using the Pre-Production machine behind the F5 by adding a line to the hosts file assigning the "auth.yale.edu" hostname to a test address.

Background on Proxies and Tunnels

The first thing to say is that in almost no modern network is the hostname of the server that the Browser uses to get to Shibboleth ("auth.yale.edu") the actual name of the VM on which Shibboleth runs. In fact, it is almost never possible for the Browser to actually talk to Shibboleth directly. For security reasons, the network addresses and firewalls are set up to block outside access to server VMs, and a front end proxy machine provides the connection between the Browser and the Server. At Yale, that Proxy machine is called the F5.

Proxies have been part of HTTP since the early days of the World Wide Web. Originally they were used when the Internet was slow and it did not make sense for hundreds of computers at Yale to each independently download their own copies of widely used web pages. Today, you can put a proxy:

  • On the same computer as the Browser. The Charles Web Debugging Proxy is a useful tool for testing.
  • You can still find a client oriented proxy somewhere in the campus network, but this is no longer common or useful.
  • The F5 sits between the secure environment of the servers in the machine room and the outside world of untrusted requesters.
  • A front end (Nginx or Apache Web Server) can receive requests on ports 80 and 443 on the Shibboleth VM and they can forward those requests to Tomcat.

As a developer testing code, you probably only have control over the first type of Proxy, and if you chose to use it then we recommend Charles Web Debugging Proxy as the simplest tool.

However, if you run a test and the SAML Request send by the SP is being rejected because the generated string does not match the expected URL, then something is going wrong and it could be with any of the other intermediate devices or it could be a Tomcat configuration problem. So you have to understand something about how this stuff works in order to debug it.

The good news is that Tomcat fully expects that one or more proxies will exist between the Browser and the server VM, so it is quite flexible in its configuration. Shibboleth is not as flexible, but the fact that it can work at all means that if you get the proxies configured right then everything will be OK.

When the Browser generates any HTTP request, it creates a Host header. This header contains the protocol, hostname, and port number from the URL that the Browser is using to get to the application. For a request that thinks it is going to production Shibboleth, this is

Host: https://auth.yale.edu

This header can go through the network and the F5 unmodified, or it can be changed. There are other headers that proxies frequently generate to indicate processing they have done. There are standards and if you have a couple of days you might find and read through all of them.

However, there are two basic rules. First, if the Browser thinks it is talking to production Shibboleth, and the rerouting is done in the network configuration, then one solution is to leave the original Host header alone. On the other hand, if the Browser knows that the test Shibboleth is really at a different URL, then it might be a good idea to have something in the proxy path that changes the Host header so it has the auth.yale.edu value shown above. In other words, if you know it is right leave it alone, and if you know it is wrong, change it.

It is trivial for Operations to fix the header, but if they are not already doing it, this will be more trouble than it is worth. Configure the client to generate the right header in the first place.

If the header is right coming out of the client, and it is being set incorrectly in the proxy chain, then you have to get Operations to fix itIn modern networks, the Browser almost never talks directly to a production server. Production servers are hidden away in machine rooms behind firewalls, and access to them goes through a network front-end device. At Yale, that device is called the "F5".

So in the simplest case, a Browser going to CAS, or Shibboleth, or any other production service actually connects to the F5. The F5 then forwards the Browser request into the machine room, and it sends back to the Browser the response from the real server.

In HTTP, when a computer stands between the Browser and the Web Server and acts as a silent intermediary, it is called a Proxy. There are actually two configurations. In the old days, the original Web Proxy was a device on the Yale Campus that held local copies of frequently used pages from distant Internet servers. That way hundreds of requests from Yale users for the same front page of the New York Times could all be satisfied by a single copy saved from a recent request. That was useful back when the Internet was slow, but today the Internet is so fast and powerful that this type of proxy has become obsolete.

So mostly today we talk about a Proxy that sits in front of a server, rather than a Proxy that sits behind the Browser. This is often called a "Reverse Proxy" and it receives requests intended for a Web Server and, in many cases, it distributes the requests that come in among a number of identical server computers to spread the work around and quickly recover if one of the servers has a problem.

The Proxy is supposed to be invisible. To the Browser, the proxy appears to be "auth.yale.edu" or whatever hostname the Browser put into the URL. If that is the case, the actual VM in the machine room where a service like Shibboleth is running will never really be named "auth.yale.edu" but will instead be "vm-shibprd-01.web.yale.internal". Furthermore, that real machine name and the IP address of that machine will not be visible outside the machine room and you can only get to it through the F5.

So you can see that if Shibboleth needs to know its own URL from the point of view of the Browser, and it insists on figuring it out for itself through programming, there is a bit of a problem. The "auth.yale.edu" name is known to the F5, but until Shibboleth gets a request from the first user, the name "auth.yale.edu" is configured nowhere on the VM and there is nothing Shibboleth can do to find it.

In HTTP the Browser puts the protocol and host name in a Host: header that is part of the data sent to the server. So coming out of your Browser, there will be a line containing "Host: https://auth.yale.edu". If that line gets to Shibboleth unchanged, then Shibboleth can use it to guess the right answer to the "What is my network name" question. Of course, the F5 or any other proxy can change this header, but then there are other network standards that have developed over time to create other Headers that track such changes.

Tomcat was written to work correctly in the modern world of firewalls, and reverse proxies, and F5 devices. It can be configured to report to the application that the hostname is "auth.yale.edu", that the data came in over "https" on port number 443, despite the fact that the data actually came in on a "http://localhost:8080" request.

Feel free to download the Shibboleth source code and read it. You will discover that there is some Shibboleth source that calls some OpenSAML source that calls back to some other Shibboleth source. Some information comes from Tomcat, some from Spring, and unfortunately when you are talking about how the CAS integration does the same thing then Shibboleth calls the Unicon code which in turn calls the CAS Client code.

Somehow under the covers this stuff digs through the HTTP headers and the Tomcat configuration and comes up with what it thinks is "The URL the Browser used or could use to communciate to this Shibboleth server". Most of the time it is right, or when it is wrong it is obvious why it is wrong. If you cannot fix it in 10 minutes, you will never fix it.

That is why the simplest solution is to put your code in Pre-Production and change the hosts table to point "auth.yale.edu" to the F5 address that routes to Pre-Production.