Showing posts with label Best Practices. Show all posts
Showing posts with label Best Practices. Show all posts

Wednesday, September 30, 2009

WCI: Varpacks and Dynamic Reload

Varpacks stands for Variable Packages…As their names show, varpacks are portal objects that do 2 main things:

  • Load values from a file into the portal memory (xml format is preferred since there is already a XMLBaseVarPack class that helps load simple XML files)
  • Help access these loaded in memory values from anywhere within the portal application – very likely from your portal “customization” code (i.e. custom activity space, custom view, PEIs, )

The goal here is not to re-explain what Varpacks are, since it is already pretty well explained in the ALUI/WCI developer documentation (4 pages):

http://download.oracle.com/docs/cd/E13174_01/alui/devdoc/docs60/Customizing_the_Portal_UI/Using_Varpacks/plumtreedevdoc_customizing_varpack_intro.htm

The goal here is to explain the following 2 points:

  1. Portal does not have always have to be restarted to load the new Varpack values from the XML file.
  2. Developed properly, a varpack can load/access “experience definition” specific values, which can be very useful when you portal powers multiple portal sites, each with their own different settings etc…

1 - First, to allow you varpack to be reloaded dynamically without the need to restart the portal, you simply need to specify it in your varpack code… and really, it is as simple as overriding the following method:

public override bool CanReloadVarPackFromUI(){
return true;
}

If the method returns true, then the varpack can be reloaded from the UI, otherwise, it cannot…and then can be reloaded only at portal startup (hence requiring portal restart if you change a value in your varpack XML file)…


And what is this UI? It is the fairly unknown “MemoryDebug” activity space (see this article from Function1 that explains how to access it: http://www.function1.com/site/2007/06/alui-portal-memory-debug-page.html).


Now, if you did everything correctly with your varpack development and deployment, you should see in the “MemoryDebug” screen your varpack name in the list of loaded varpack, and a “view” button by it…And if you returned “true” on the overridden CanReloadVarPackFromUI method as shown above, then a “Reload” button will also show up. As you imagine, clicking “reload” will launch the process that loads the values from your varpack XML file into portal memory, hence reloading your new Varpack values without having to restart the portal.


2 – Secondly, let’s imagine your single portal environment powers multiple portals, each with their own style, colors, hostname…etc…well it is easy to imagine, really: that’s what we do almost every time, and that’s what portal is for.


But now, let’s imagine that you built these customization that should be loaded only within portal site A, but not within portal site B…In other word, you want to selectively load your customizations based on criteria such as portal hostname or experience definition ID…mmmmm that is not really possible since your customizations (view replacement, PEIs, custom activity space, etc…) are dynamically loaded when the portal starts and activated directly once loaded…


But with the use of a properly developed Varpacks, you could actually achieve the above scenario easily…


What you need to do is to make your Varpack aware of the experience definition you are currently in, and then define in your XML file variable names suffixed with an experience definition ID.


Here is a sample XML file:


<?xml version="1.0" encoding="UTF-8"?>
<MyCustomVarpack>
<Section1-200>
<mycustomkey1 value="" />
<mycustomkey2 value="" />
<mycustomkey3 value="" />
<mycustomkey4 value="" />
</Section1-200>
<Section2-201>
<mycustomkey1 value="" />
<mycustomkey2 value="" />
<mycustomkey3 value="" />
<mycustomkey4 value="" />
</Section2-201>
</MyCustomVarpack>

As you can see, the sections have an ID appended to it…this ID represents the experience definition ID where the values within this section will be applicable….And as you can see, using this name formatting, you can potentially define completely different values for experience definition 201.


Now, how to make your Varpack class aware of the current experience ID you are in…well you simply need to store the experience definition ID in an instance variable of your varpack object…see the code below:


public class MyCustomUIVarPack : XMLBaseVarPack
{
private static OpenLogger log = OpenLogService.GetLogger("MyCustomUIVarPackLibrary",typeof(MyCustomUIVarPack ));

private int m_ExpId = -1;
private void SetExperienceId(int expDefId)
{
m_ExpId = expDefId;
}
... ...
... ...
}

Then, to assign the current experience definition ID to this instance variable, you need to find the experience definition ID you are in using the call: TaskAPIServerSubPortal.GetSubPortalCachedObject(oUserSession)…


And then, simply assign the ID to the variable using the defined setter SetExperienceId(int expDefId)…here is the code:


//getting the varpack instance
MyCustomUIVarPack customVarpack = (MyCustomUIVarPack)vPackMgr.GetVariablePackage(MyCustomUIVarPack.VARPACK_ID);

//getting the experience definition using the user session
IPTSubPortalInfo objSubportalinfo = TaskAPIServerSubPortal.GetSubPortalCachedObject(oUserSession);
If(null != objSubportalinfo)
{
Log.Debug("Subportal Info Object ID is: {0}",objSubportalinfo.GetObjectID());
customVarpack.SetExperienceId(objSubportalinfo.GetObjectID());
}

Ok, with that done, your varpack object is now “experience definition aware”…and as such, you can simply override the Varpack GetValueAsString / GetValueAsBoolean / GetValueAsInt methods, appending the experience definition ID to the varpack key you want to get the value from.


I hope this article will give you a couple of new ideas in regards of Varpacks…but really will make you realize (if not already) that the WCI Varpack framework is definitely pretty cool and powerful.


As always, let me know what you think…and let me know if you used varpacks to implement other cool use cases…

Monday, May 11, 2009

ALUI Webcenter Grid Search: Maintaining the search cluster repository without loss of service

Sometimes, for maintenance reasons, the cluster repository has to be unavailable for a short amount of time (I.e. the NAS on which it is hosted is patched and need to be restarted, or the central search cluster repository needs to be moved from one server to another, etc…).

The main problem is that search relies heavily on the availability of search cluster repository in order for the portal content to be properly indexed (for example, the cluster registers any new index delta and ensures that these delta are redistributed to each node’s local index, that way the search nodes are always in sync with one another). Unfortunately, I’ve noticed many times that when the cluster becomes not available for as short as a couple of seconds, the search infrastructure does NOT handle this gracefully…

At best, the nodes all go in “read-only” mode automatically (meaning the nodes act only as query service instead of query+index service), corrupting most of the time the process handles of the node being the “indexer” at the time of disconnection (you’ll see “invalid handles” errors in the search status screen for example)…at worse, all the nodes shutdown with a great “out of memory” error. Both scenario is not a good one, since it will not go back in run mode automatically after the disruption is over, and will probably require a overall restart of nodes.

If you need to do this in PROD where uptime is usually a strong requirement, then the idea is to do such an operation without jeopardizing the search capabilities of your portal site(s). Indeed, search being so central to portal, when down, many portlets or components relying on search will be down, and overall service will be pretty degraded.

Fortunately, search comes with a powerful admin utility: cadmin.exe. You can find it on any of your search nodes, usually at the following path:

<pt_search_home>/bin/native/cadmin.exe

Using the tool, you can gracefully put all the search nodes in “read-only” mode before the maintenance operation. Indeed, when the nodes are in read-only mode, each node act as a “disconnected” query service, providing search results solely based on their local index. While in that state, the search cluster can be fully unavailable… and apart from any new content not being indexed, end users will not see any search disruption.

So here are the commands you would want to perform, either manually or in a batch:

cadmin runlevel readonly –-> this puts all the nodes of the cluster in readonly mode
cadmin status –-verbose –-> this give you the status of the cluster. useful to make sure the previous operation worked as expected.

…perform your maintenance operation…

cadmin runlevel run –> put all the nodes on the cluster back in run mode
cadmin status –verbose –> sanity check…

What you would want to do before any search maintenance is perform a search checkpoint (in other word search backup). 2 options: doing it manually using the Admin UI, or using the cadmin tool as follows:

cadmin checkpoint --create

As an extension of this, you can check out the other operations you can perform with the cadmin tool (pretty much everything you can do with the search cluster admin UI, with more power added to it) by entering cadmin –help

Hope that helps. Until next time, take care!

Sunday, November 16, 2008

ALUI / WebCenter Interaction: Introduction to Native API development (Part 1)

Most of the time, creating a remote portlet application using the standard IDK is enough. Indeed, commonly, you just need to access user profile information, portlet ID, page ID etc... or perform simple operations exposed by the IDK PRC API.

But if you hit the limits of the IDK, it is not the end of the road. In the ALUI/Webcenter development documentation, they explain how to perform various UI customizations such as view replacement, PEI development, Activity Spaces creation or extensions, etc... All these are created within the portal application itself...Another option is to create what I call a "Native API Portlet Application". As its name indicates, this portlet application accesses directly the portal API and can perform virtually any operation that the portal can do...very powerful (but non supported :) so make sure your application is well written so that you can change the portal API access layer easily if you upgrade the portal version for example)

First, the 2 main requirements in order to create a Native API application are:

  • The application needs to be on the same server as Portal, or Automation, or API service
  • The application needs to reference various portal DLLs (located in /ptportal/6.1/bin/assemblies for dotnet, or /ptportal/6.1/lib/java for java). You don’t need them all. Here is the minimum list:



    ptportal\6.1MP1\bin\assemblies\opencache.dll

    ptportal\6.1MP1\bin\assemblies\openconfig.dll

    ptportal\6.1MP1\bin\assemblies\opencounters.dll

    ptportal\6.1MP1\bin\assemblies\openfoundation.dll

    ptportal\6.1MP1\bin\assemblies\openhttp.dll

    ptportal\6.1MP1\bin\assemblies\openkernel.dll

    ptportal\6.1MP1\bin\assemblies\openkernelsearch.dll

    ptportal\6.1MP1\bin\assemblies\openkernelsearchimpl.dll

    ptportal\6.1MP1\bin\assemblies\openlog-framework.dll

    ptportal\6.1MP1\bin\assemblies\openprocman.dll

    ptportal\6.1MP1\bin\assemblies\opensharedcache.dll

    ptportal\6.1MP1\bin\assemblies\opentempfile.dll

    ptportal\6.1MP1\bin\assemblies\openusage.dll

    ptportal\6.1MP1\bin\assemblies\openusage-api.dll

    ptportal\6.1MP1\bin\assemblies\openusage-impl.dll

    ptportal\6.1MP1\bin\assemblies\plumtreeserver.dll

    ptportal\6.1MP1\bin\assemblies\portal.dll

    ptportal\6.1MP1\bin\assemblies\pthome.dll

    ptportal\6.1MP1\bin\assemblies\ptportalobjects.dll

Important note: It is perfectly allowed to also include the IDK Dlls here too... and I find it particularly recommended if you are writing a native API portlet (for instance getting the current login token for example is fairly easy using the IDK API)

Second, you need to create the native session (everything starts from here, really):

1: String strServerConfigDir = ConfigPathResolver.GetOpenConfigPath(); 
2: IOKContext configContext = OKConfigFactory.createInstance(strServerConfigDir,"portal");
3: PortalObjectsFactory.Init(configContext);
4: IPTSession ptsession = PortalObjectsFactory.CreateSession();

From there you actually need to connect this session with a particular user identity. That way, the session object will be aware of your identity and especially the security and permission associated with your identity. In other words, even if you are using the native API, you cannot do more than you are allowed to.

To connect, 2 main options:

  • Use the login token that you can simply get from the IDK API (that is prefered option if you can)
1: String loginToken = m_portletRequest.GetLoginToken(); //IDK call
2: ptsession.Reconnect(loginToken);
  • Use explicit Username (or user ID) / Password to connect.

1: String username = "myusername";
2: String pwd = "mypassword";
3: ptsession.Connect(username, pwd, null);

Third (and Final), you access the right ObjectManager Class depending on which type of portal object you want to interact with.

When the session is created (that was pretty easy, right?), that is when you can actually start interacting with the portal internals...and a majority of actions goes through the PTObjectManager objects (IPTObjectManager interface). For instance:

1: IPTCommunityManager ptCommManager = ptSession.GetCommunities(); //for community objects
2: IPTPageManager ptPageManager = ptSession.GetPages(); //for community page objects
3: IPTObjectManager ptGadgetManager = ptSession.GetGadgets(); //for portlet objects
4: //etc...

You noticed that for portlets, there is not a IPTGadgetManager insterface....that’s ok as all the "Manager" interfaces are children of the base IPTObjectManager interface.

Although the vast majority of manager objects are accessible through a direct ptsession.Get() call, you can also get the right manager using the generic call below (using the classID of the object type you want)

1: IPTObjectManager ptCrawlerManager = ptSession.GetObjectManagers(PT_CLASSIDS.PT_CRAWLER_ID); 
2: //using     the class id of the object type you want

From there, the freedom is yours... and various operations will be available depending on the manager you called. One call for instance that all managers have is the open object:
1: ptObjectManager.Open(objectid, lockObject);

With this call, you get directly access a particular object in the portal, and interact with it as if you were in the UI

In the next article, I will show you how I package these API call in a standalone library to minimize as much as possible any API call within the presentation layer code...

Monday, June 30, 2008

ALUI Publisher - Part 2: Increase Performance by enabling REAL Caching

In my previous post http://fsanglier.blogspot.com/2008/02/alui-publisher-increase-performance.html(man, already couple of month ago...I know I've been sucked into a black hole since then :) ) I was talking about how to best design a scalable and redundant ALUI Publisher architecture. But what I had not pushed enough in the last article was performance.

In my opinion, the Publisher standard behavior for serving content has some performance flaw (at least in ALUI 6.1 - Publisher 6.4) related to caching... Since there are ways around this (that's what we do, right?), I think you might benefit from this a lot, and in my last implementation, the change explained below increased performance under load to complete new levels (in the meantime reducing DB requests and DB and publisher redirector CPU utilization)...So here it goes...

As I explained in previous post, each published content portlet within a portal page are going to make a request to the Publish Content Redirector component, and particularly the JSP page in charge of performing the redirect: published_content_redirect.jsp (you can see that defined in the Published Content portal web service object). As the name says, this Java Server Page (JSP) performs a 302 redirect to the published content item (as seen in previous post, this location should be served by your favorite web server, apache or IIS for example...). But BEFORE making this redirect, it must know where to redirect to... so for that, the code makes a DB request to the publisher Database in order to get the browsing path to the published content item (passing the publisher content item ID that was saved when you created your published content portlet earlier).

Ok so here is the first flaw I was taking about in previous paragraph: To be able to see some content through the publisher portlets within the portal page, you can see from the above explanation that multiple calls to the publisher DB will be made. Let's say we have 5 publisher portlets on the page (not uncommon), for each page rendering for 1 user, 5 DB calls will be made to the publisher DB (in addition of multiple other DB calls for portal and analytics). If we are now talking about thousands of users, we are talking about too many DB calls to simply see some content that does not change often. This has an unnecessary impact on DB load of your infrastructure, and will increase the page load consequently since DB calls are inherently slower that simple content rendering...

While reading, some of view are already thinking for a good reason: CACHING! Yeah, indeed, caching is the secret to scaling and performance (not always necessary to take out the big bucks and supercharge even more the DB infrastructure). And great for us, the portal offers a great out-of-the-box caching capability within the web service object: simply set the minimum caching to 2 hours, max to 20 days, and normally, you would think that the portal should simply cache the published content for that amount of time...removing the need to call the published_content_redirect.jsp altogether, and thus the need to make a DB call!! ...but it does not happen this way. You don't believe me? Enable access logging on publish content redirector components (un-comment "Access logger" section within <ALUI HOME>\ptcs\6.4\container\deploy\jbossweb-tomcat50.sar\server.xml) and you will clearly see that even though your page contains only published content portlets that should be cached, the published_content_redirect.jsp  is still constantly called...and thus caching is not really....caching.

Why does this happen? It is because of the redirect mechanism for serving content...From www.w3.org, 302 is explained this way: "The requested resource resides temporarily under a different URI. Since the redirection might be altered on occasion, the client SHOULD continue to use the Request-URI for future requests. This response is only cacheable if indicated by a Cache-Control or Expires header field." Thus, the portal is doing is job perfectly (it acts as a client here) and will never cache a response with a temporary redirect 302 status code.

Ok so what can make it better? Changing the redirect mechanism to something that does not redirect...Well, using this other JSP actually already present and developed within ALUI 6.4 (I have not verified if present in earlier versions of publisher): published_content_noredirect.jsp. Instead of issuing a redirect to the published content, this jsp performs an HTTPGetRequest to it and write its content to the JSP output stream. The response code is now a simple 200 OK ("The request has succeeded" - www.w3.org) that can be cached by the portal. To enable this, simply change the HTTP url of the Published Content Web Service Object to be published_content_noredirect.jsp instead of published_content_redirect.jsp. Of course, check out the publisher redirector access logs to see the dramatic difference...under load, you will initially see a bunch of requests to published_content_noredirect.jsp, but very very fast, the access log becomes silent, all the content being really cached by portal...

Result?? You can increase the load even more, and the page response satys the same (or is even better), and the DB utilization is not altered by that load...you simply have a site that is so much more performant. Our initial results showed that under constant intensive load (with and without the change) the publisher infrastructure would not crash anymore, the CPU usage of both DB and publisher redirectors would be consequently diminished, the number of DB requests would drop, and the load could actually be increased to new levels without loss of performance and functionality, thanks to caching.

Since this post is already long, I am going to stop here for now...Please read next post (http://fsanglier.blogspot.com/2008/06/alui-publisher-part-2-increase_30.html) to understand the second flaw: the published_content_noredirect.jsp has a truncation bug...that is fixable of course :)

So long!

Tuesday, February 26, 2008

ALUI Publisher: Increase Performance, Scalability and Availability

ALUI publisher is the component that provides out of the box Web Content Management for the ALUI portal. Depending on the nature of your portal, Publisher can be an important or even critical part of your portal infrastructure (ALUI-powered Internet sites for example, or intranet with a lot of static content displayed through portlets).

So if this component is really critical, the architecture design for that component must provide performance, scalability and redundancy. This article is meant to show you how to design Publisher Architecture to maximize performance, scalability and redundancy, and ultimately provide the best experience to the end user.

Published Content portlets - How it works:

First, let's lay out all the key components and understand the request flow for each Publish Content Portlet on a single portal page:

   PubContentRequestFlow_thumb_1

It is important to reiterate that this flow is not per portal page, but per portlet. In other words, a portal page with 4 published content portlets will initiate 4 simultaneous request flows like the one above. From that, you can understand that depending on the load of these portal pages, the number of requests to the redirector and the publish content services could easily skyrocket, which is a strong proponent of clustering these components.

The redirector, as its name states, will simply redirect the request to the right content url, based on the content ID that is given. Since this component actually makes more intensive DB calls and is accessed for every pub content requests (when content is not cached by the portlet of course), we definitely would want to cluster it and allow for future addition to that cluster when the load increase.

The published content piece is a very simple "static web content serving solution". Although JBOSS or any other application servers are able to serve static content, none are as performant as true web servers optimized for the task: Amongst others, Apache or IIS are good possibilities.

The problems:

The main problem consist in the fact that the installer does not provide any tip to help you achieve that. By default, Publisher installer provides 2 options: Full Component (it means publisher engine, workflow engine, and the embedded redirector) or Publish Content Redirector Only.

A couple of common shortfall if out of box design is followed:

  • Publisher engine (explorer) cannot be clustered.
  • Publisher internal application server (JBOSS) is serving publisher, workflow, redirection, and published content.
  • Publish Content Redirector standalone is not optimized for serving static content (it is used mainly to redirect to the actual publish content url, based on the requested publisher item ID)

The Solutions:

Ultimately, what we want to do is decouple each component from each other in order to scale it independently from the others. Thus, what we want to improve through architecture design consist in:

  • Publisher and workflow engine set up in failover mode. (Hot-Warm or Hot-Cold failover)
  • Publish Content Redirector Load balanced using Hardware (F5 BigIP, Cisco LB) or software load balancer.
  • Publish Content Served by appropriate web server (apache or IIS), optimized to best deliver static content (best performance)...instead of the publisher internal jboss app server (better optimized for dynamic J2EE content delivery).
  • Publish Content Web Server (apache or IIS) to be load balanced using Hardware (F5 BigIP, Cisco LB) or software load balancer.

Following that design, the redirector can be scaled independently from the publish content serving mechanism, as well as from the publisher admin. And also, if the server that hosts publisher is down, the redirector services and publish content services are still able to provide content without any problem. Similarly, since the redirectors and pub content web servers are load balanced, they are fully redundant, providing maximum availability of static content on your ALUI powered internet site for example.

So how do we tie everything together? Here is an overview of tasks that corresponds to what we talked about until now: (here using 4 servers in my example...could use more or less depending on what hardware is available to you...with a minimum of 2 servers of course.)

  1. Install full Publisher on Server A (contains redirector capability by default)
  2. Import the publisher objects in the portal (pte file)
  3. Install redirector component on Server B
  4. Install Apache/IIS on server C and D
  5. Create the 3 load balancing pools, 1 for Publisher (useful for HOT-WARM failover), 1 for Redirector, 1 for publish content web server.
  6. In publisher explorer, set the "publishing target" to a fault tolerant and fully redundant file share. (clustered NAS for example)
  7. Still in "publishing target" screen, set the browsing url to make sure it access the publish content web server pool (and as such access the Apache/IIS web servers)
  8. Setup Apache/IIS web servers on C and D in order to expose the published content that is at the "publishing target" set up previously
  9. We need to modify the publisher portal objects in order to make them access the correct load balancing pools
    1. Change PubContent Web Service Url to make it access the redirector load balancing pool.
    2. Also, change accordingly the gateway prefixes of the PubContent Web Service, especially the ones related to published content (publish/preview)
    3. Make sure the publisher url is actually going to the LB instead of going directly to publisher.

One last thing you might want to do to still increase performance: Make sure you publish the images to the image server instead of the publish content repository. (Since the image server is publicly accessible from the internet, do this only if the images you are working with are not exposing information that should not be publicly accessible!). This is explained by the fact that serving binary content through the portal gateway component is much slower than serving the content directly to end user.

Et Voila! When you are done configuring all that, you have a publisher infrastructure that is completely redundant in every aspects, offers maximum scalability for each critical components, as well as  maximum performance for serving static content.

Saturday, November 17, 2007

BEA Aqualogic Portal (ALUI) - Single Sign On (SSO) Concerns and Techniques

As explained very well on this great post "Changing SSO Settings" from Function1, it is highly recommended to protect only the "SSOServlet" (default path= /portal/SSOServlet) when you want to SSO-enable the ALUI Portal. As I worked recently with an integration of ALUI with CA Siteminder, I am going to go a little bit further so that the SSO solution is complete.

But first, the 2 benefits of protecting only SSOServlet are:

  • Performance (as explained in Function1's post)
  • Enable guest access to the portal with same url (the portal is the gate, not the SSO agent)

But the main concerns are related to the SSO Session versus the Portal Session. As explained in Function1's post, the timeouts of portal and SSO agent should be in sync so that the user is actually logged out when the portal session times out (20 minutes by default). As it is well explained, you want both timeout to be very close, the portal timeout being trigged a bit before the SSO timeout.

But that's where I want to go just a little further...timeout sync is not enough to make the system perfect. Indeed, 2 extra use cases exist (and are not covered yet):

  1. SSO session "keep-alive"
  2. SSO session Logged out.

SSO session "keep-alive"

Basically, after the user successfully logged into ALUI portal (using SSO login screen), a SSO token has been created for its session (SSO cookie embedded in the browser session). But the problem is that after a successful login, the portal won't call SSOServlet again, and thus the SSO agent (generally on the web server front end, or the application server hosting the portal) has no longer anything to say about the traffic going through its agent since it is all unprotected from its point of view. Actually, it is as if the agent is not even seeing that traffic at all. Why do we care?? Well, the SSO session timeout is only refreshed if the agent is actually seeing any protected traffic. When the agent is not seeing any protected traffic, the timeout count down starts.

So to sum up, when the user successfully logged in the portal and is browsing the portal protected content, it is as if the session was idle from the Siteminder point of view. That is perfectly fine (at least you wont notice the problem) if you only use SSO for the portal. But imagine you use SSO for any other application in your enterprise (which is the use of SSO by the way :) ), or even portlets within your ALUI portal, then you probably don't want your SSO session to timeout while you are browsing the portal. Otherwise, after 20 or 30 minutes (whatever is set up on your SSO system for SSO timeout), you will still be able to browse the portal fine (since you are not idle from the portal point of view), but your SSO Session WILL HAVE TIMED OUT...and you will have to login again if you go to another of your favorite enterprise SSO protected sites...

So how can we make that work?? How can we ensure that the SSO session (or SSO token) is "kept alive" while we browse the portal?? Very simple trick actually: I basically created a dummy SSO protected content on the front end web server (for example http://portal.com/sec/dummy.html) and embedded that url in an invisible iframe in every portal pages (well suited for the footer portlet of your portal, or better, put that in your favorite liquidskin component - see my liquidskin ongoing serie "Overview of BEA ALUI LiquidSkin: Part 1" and "Overview of BEA ALUI LiquidSkin: Part 2")...

Basically, you have <iframe src="http://portal.com/sec/dummy.html" width="0" height="0"></iframe> at the bottom of every page you wish...it seems low tech, but works pretty well: every portal pages that have that footer portlet will initiate a request to that protected url, letting the SSO agent know: Hey, i am not idle, my session is still alive!!

Ok, good...but I am still not happy yet :)

SSO Log out

When you logout from the portal, you also want the SSO session to be logged out too. this is easy enough with CA siteminder: in the SSO policy you just provide the log out pattern to look for (usually something like /portal/server.pt?open=space&name=Login&control=Login&doLogout=&clearsession=true">/portal/server.pt?open=space&name=Login&control=Login&doLogout=&clearsession=true">/portal/server.pt?open=space&name=Login&control=Login&doLogout=&clearsession=true">http://<portal>/portal/server.pt?open=space&name=Login&control=Login&doLogout=&clearsession=true) and the SSO agent (remember it is on your front end web server or application server) will kill the SSO token if it intercept such a pattern in the request url. Cool!! That way, when you click log off in the portal, you are actually logged out.

But again, let's imagine we have multiple systems that uses the SSO session. You first loggedin the portal, browse it a little, and then decide to go to this other SSO-protected application. Then you decide you are finished and logout from there. What happens if you log out from another system apart from the portal?? Well if you don't do anything special, you will logoff from this other application, which will normally kill the SSO session (same "finding logout url pattern" technique)...but if you go back to the portal after that (and you were previously logged in)...oh surprise, you can go in no problem!! Well that's normal, your portal session is not over yet (provided that you were not away from the portal more than the portal timeout) and you did not do anything to finish it...

But that is not how it should work, right? If the SSO session is over (by logging off from any SSO protected system), you should not be able to go in any other SSO protected system!! Just imagine if your favorite banking web site was working this way...you logoff from your savings account, but your checking account interface is not logged off...I would not particularly like that from a security point of view :)

So we have to deal with it: I see 2 options in order to make sure all your systems are logging out when 1 is logging out:

  • Having an independent logout page that initiates logout requests for all the protected applications in your enterprise (for example an HTML page containing as many <img> tags or <iframe> tags as you have application to log out) -- I don't like this method so much because I will have to maintain this central logout page as soon as I add / remove a protected application in my environment,
  • Making applications log out on their own if the SSO token is not there. (or at least forcing any requests to SSO login if the SSO token is not present in the request)

The second solution is to me the best since it works once and for all. But it is a little more complex than the first one since we are protecting only the SSOServlet...(if the site was fully protected, that would work without doing anything...the agent would not see the SSO token and would not let you pass as long as you don't authenticate successfully)

How can we do that in the portal? I chose to implement a JAVA filter (I was working with JAVA portal with that client) that checks for SSO token presence (you can implement the same filter functionality in DOTNET too: it is called http module). The simplified logic is:

  • If SSO token is present and valid, do nothing,
  • Otherwise, force portal logout (if you actually previously logged in)...which will make the request being redirected to SSO login...

Et Voila! That way, the portal will logout nicely, on his own, when no SSO token is found.

I hope this helps you better understand the different concerns of implementing Single Sign On with your favorite ALUI portal (would actually apply to other portals too)