Ending an APM session when browser tab is closed

Code is community submitted, community supported, and recognized as ‘Use At Your Own Risk’.

Short Description

Ending an APM session when a user is closing the browser tab. 

Problem solved by this Code Snippet

Sometimes an user stops using an application delivered via APM by closing the browsers tab. When this happens it's most likely that the APM session remains active until it times out. In general this shouldn't be a problem, but in some specfic situations ending the active APM session when the browser tab is closed may be required. This will force the browser to enter the APM policy from scratch when reconnecting to the APM delivered application.

How to use this Code Snippet

This code snipet is an iRule which uses the STREAM-profile. This iRule will inject a little bit of JavaScript that will interact with the F5 BIG-IP to determine if the active APM session needs to be terminated.

NB: Please note that this solution which is using the beforeunload event will probably not work for mobile platforms. See: Don't lose user and app state, use Page Visibility - igvita.com

Code Snippet Meta Information

  1. Version: 1.0
  2. Coding Language: Tcl /  JavaScript

Full Code Snippet

 

when CLIENT_ACCEPTED {
    ACCESS::restrict_irule_events enable
}

when HTTP_REQUEST {
    # Disable the stream filter by default   
    STREAM::disable 

    # LTM does not uncompress response content, so if the server has compression enabled
    # and it cannot be disabled on the server, we can prevent the server from
    # sending a compressed response by removing the compression offerings from the client
    HTTP::header remove "Accept-Encoding"
    
    # don't terminate an active session (a page reload will set this variable to 0 again)
    ACCESS::session data set session.custom.terminate_session 0
    
    if { [HTTP::uri] starts_with "/f5/remove_session" } {
        log local0. "DEBUG: received request to terminate session"
        ACCESS::session data set session.custom.terminate_session 1 
        
        after 1000 {
            # this session can be terminated if still inactive for 1000 ms
            if { [ACCESS::session data get session.custom.terminate_session] eq 1 } {
                log local0. "DEBUG: terminate_session"
                ACCESS::session modify -sid [ACCESS::session sid] -timeout 1
            }
        }
    }
    
    set uri [HTTP::uri]
}

when HTTP_RESPONSE {
    if { ([HTTP::header "Content-Type"] starts_with "text/html") && not ($uri starts_with "/saml/") } { 
        STREAM::expression {@</title>@</title>
    <script type="text/javascript">
      if ('sendBeacon' in navigator) {
        window.addEventListener('beforeunload', function() {
          navigator.sendBeacon(
          '/f5/remove_session',
          'All your base are belong to us');
        }, false);
      }
    </script>@}
        STREAM::enable
    }
    
    unset uri
}

 

 

Updated Dec 14, 2023
Version 2.0
No CommentsBe the first to comment