Suppress MFA for a period of time

Problem this snippet solves:

This code snippet can be used if you want to suppress MFA for a period of time. This solution uses an encrypted persistent cookie, that will be set at a successful MFA logon. Upon subsequent logons the browser will send the persistent cookie (when not expired) and the cookie will be validated. When the cookie is valid, the 2nd authentication factor will be skipped.

How to use this snippet:

Create an Access Policy which uses MFA. For example see the following picture.

Note the following VPE agents in the example above: 'iRule Event - Check Cookie', 'Suppress MFA' and 'Variable Assign - Set Cookie'. These events need to be in place to cooperate with the iRule in this code snippet.


iRule Event - Check Cookie



Empty Event - SuppressMFA


Add a new Branch Rule named 'Yes' and add the following expression:


expr { [mcget {session.custom.suppressmfa.skip}] == 1 }



Variable Assign - Set Cookie


Code :

when RULE_INIT {
    # change passphrase below before any publishing
    # set seconds after which the peristent cookie expires
    array set static::suppress_mfa {
        passphrase "hEuoYjmFUpB4PcpO3bUdQtLP4ic7jjm"
        cookie "SuppressMFA"
        seconds 86400
    }
}

when ACCESS_SESSION_STARTED {
    # store hash from cookie in APM variable
    if { [HTTP::cookie exists $static::suppress_mfa(cookie)] } {
        set hash [HTTP::cookie decrypt $static::suppress_mfa(cookie) $static::suppress_mfa(passphrase)]
        ACCESS::session data set session.custom.suppressmfa.hash $hash
    }
}

when ACCESS_POLICY_COMPLETED {
    # if cookie should be set, create hash and store it into a APM variable
    if { [ACCESS::session data get session.custom.suppressmfa.setcookie] == 1 } {
        set username [ACCESS::session data get session.logon.last.username]
        set UA [ACCESS::session data get session.user.agent]
        set hash [b64encode [md5 "c:$username:$UA"]]
        ACCESS::session data set session.custom.suppressmfa.hash $hash
    }
}

when ACCESS_POLICY_AGENT_EVENT {
    # check if hash from cookie matches current session hash (username and user-agent)
    switch [ACCESS::policy agent_id] {
        "checkcookie" {
            set username [ACCESS::session data get session.logon.last.username]
            set UA [ACCESS::session data get session.user.agent]
            set hash [b64encode [md5 "c:$username:$UA"]]
            if { $hash equals [ACCESS::session data get session.custom.suppressmfa.hash] } {
                ACCESS::session data set session.custom.suppressmfa.skip 1
            }
        }
    }
}

when HTTP_RESPONSE {
    # if cookie should be set, insert an encrypted cookie containing the hash (username and user-agent)
    if { [ACCESS::session data get session.custom.suppressmfa.setcookie] == 1 } {
        HTTP::cookie insert name $static::suppress_mfa(cookie) value [ACCESS::session data get session.custom.suppressmfa.hash]
        HTTP::cookie expires $static::suppress_mfa(cookie) $static::suppress_mfa(seconds) relative
        HTTP::cookie encrypt $static::suppress_mfa(cookie) $static::suppress_mfa(passphrase)
        HTTP::cookie path $static::suppress_mfa(cookie) "/"
        HTTP::cookie secure $static::suppress_mfa(cookie) enable
        ACCESS::session data set session.custom.suppressmfa.setcookie 0
    }
}

Tested this on version:

13.0
Published Jul 16, 2019
Version 1.0