I don't do this anymore. My IdP hosts are behind an F5 traffic manager these days.

As described numerous places the IdP is a stateful system and to cluster it requires sharing of state information between cluster members. As is well known this synchronization is difficult and prone to failure.

An alternative is to eschew the sharing and provide a means for browsers to maintain affinity with a single member of the cluster. This can be accomplished with Apache rewrite and proxy directives.

Feature Limitations

Clustering by browser affinity eliminates any features that do not involve browser interaction.

  • Artifact Bindings
    • Unsupported.
    • Artifact mappings are managed in memory and have to be available across nodes because they can be created on one node (via front channel) but then dereferenced on another (via back channel). So no artifact-based bindings can be used.
  • Attribute Queries with Transient IDs
    • Unsupported.
    • Same reason as artifact support. You have to push the attributes.
  • Single Sign-On
    • Supported I think.
    • I use RemoteUser, but I think the many of the other login schemes, e.g. Username/Password, would work.
  • Standalone Tomcat
    • Unsupported
    • You have to frontend your IdP with Apache.
  • ConsistentClientAddress
    • Unsupported
    • You have to turn off the IdP's cookie check for a consistent client address. Proxied requests will appear to be coming from a peer idp instead of from the user.

Affinity by proxy

A cookie is defined that contains the identity of node with which a browser has a session. On each request:

  • If a cookie for a different node is found, the request is proxied to that node.
  • Otherwise a cookie for the local node is created.

Here is an example that runs on idp1, with a peer at idp2.

# if user has session on remote host, send there now
RewriteCond %{REQUEST_URI} ^/idp/profile/ [OR]
RewriteCond %{REQUEST_URI} ^/idp/Auth
RewriteCond %{HTTP_COOKIE} uwidphost=idp2
RewriteRule ^/idp/(.*)$$1 [P]

# else set our cookie
RewriteCond %{REQUEST_URI} ^/idp/profile/ [OR]
RewriteCond %{REQUEST_URI} ^/idp/Auth
RewriteRule ^(.*)$  - []

The affinity cookie is set to expire in a short time, five minutes in the example. This allows a node to be smoothly taken out of the cluster. Within ten or twenty minutes all cookies to the dropped node will have expired.

In the event of a sudden disappearance of a node, a system or tomcat crash (We are assuming that someone or something can detect the failure and drop the node from DNS), we want to stop proxying users to the dead node. To do that we drop the affinity cookie on any 503 error from any peer.

ProxyTimeout 15
ProxyErrorOverride On
ErrorDocument 503 /error503.cgi

where the error document clears the cookie and issues an error message, i.e.,

# clear idp affinity cookie and report error
cat << END
Expires: Sat, 1 Jan 2000 01:01:01 GMT
Pragma: No-Cache
Cache-Control: max-age=-8705554
Set-Cookie: uwidphost=idp1;path=/;Secure;;expires=Fri 11 May 2012 09:00:00 AM PDT;

The login system experienced an error!
Please retry your login.

If the problem persists, contact <email> or telephone xxx-xxx-xxxx for assistance.

Inhibit the consistent address check

This is an init parameter for the idp session filter