Forum Discussion

NetSnoopy's avatar
NetSnoopy
Icon for Cirrus rankCirrus
Sep 28, 2018

2 factor authentication with different timeouts

I have some APM policy working with one and two factor authentication. But now we need to have a two factor authentication with different timeouts for the second factor. Example: Client connect in the morning and have a full login with 2 factor. First is LDAP second is RSA over Radius. After 2 hours the client come back and need a re authentication but now we want to check only LDAP. But after one day we want both factors. Idea is to write an additional cookie with encoded string of username and last logon. Then the F5 can check this during the authentication and/or set. But I don’t know how.

 

Thanks for our help

 

  • Hi NetSnoopy, I think that is easier if you use a per-request policy. Let me explain. You set a 2 factor auth policy with a 1 day max session timeout. Join this policy to your VS. Create a PerRequest policy with a single factor auth (AD) with a smaller Sucsession timeout (2 hour). In this way you can obtain your goal without need of cookies.

     

    regards

     

    Leonardo

     

  • Hello Leonardo, your idea is interesting. I tried to configure but the per request Policy has only a small range of option. Most only a group check. I don't know how I can use this in my case.

     

  • Hi,

     

    you can use this code:

     

    when RULE_INIT {
       set static::session_restore_aes_key "AES 256 affeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe"  ; AES Key to protect and validate recovery data
        set static::session_restore_aes_key [AES::key 256]  ; AES Key to protect and validate recovery data
         Define here all session variables used to build client fingerprint
        set static::host_fingerprint_sources {
            session.user.ipgeolocation.country_code
            session.user.agent
         }
    }
    when ACCESS_SESSION_STARTED {
         Build client fingerprint and write it in session variable
        set data_decoded ""
        foreach source $static::host_fingerprint_sources { append data_decoded [ACCESS::session data get $source]}
        set session_hash [sha1 $data_decoded]
        ACCESS::session data set session.custom.fingerprint $session_hash
         Check if user already success OTP challenge. if true, provision session.custom.username variable with username of previous session stored in cookie
        if { [HTTP::cookie exists HostToken] } {
             Cookie content is secured by a AES key (generated each time irule is loaded)
            set cookie_content_list [AES::decrypt $static::session_restore_aes_key [b64decode [HTTP::cookie value HostToken]] ]
            if {($session_hash == [lindex $cookie_content_list 2]) && ([ACCESS::session data get session.user.starttime] < [lindex $cookie_content_list 1])} {
                ACCESS::session data set session.custom.username [lindex $cookie_content_list 0]
            }
        } 
    }
    
    when ACCESS_ACL_ALLOWED {
        if {[HTTP::path] equals "/fingerprint_accept" } {
            set cookie_expire_absolute [expr {[ACCESS::session data get session.user.starttime] + 24*3600}]
            set cookie_expire_date  [clock format $cookie_expire_absolute -format "%a, %d-%b-%Y %H:%M:%S GMT" -gmt true]
            set cookie_content_list [list [ACCESS::session data get session.logon.last.username] $cookie_expire_absolute [ACCESS::session data get session.custom.fingerprint]]
            set cookie [format "HostToken=%s; path=/; expires=%s;Secure; HttpOnly" [b64encode [AES::encrypt $static::session_restore_aes_key $cookie_content_list]] $cookie_expire_date]
            ACCESS::respond 302 noserver Location [binary format H* [URI::query [HTTP::uri] redirect]]  "Set-Cookie" $cookie
        }
    }

    In VPE, just after authentification, create an empty box with branch expression:

     

    expr { [mcget {session.logon.last.username}] == [mcget {session.custom.username}] } 

    This expression lead to bypass OTP

     

    then after successful OTP branch, create a variable assign box with content

     

    session.server.landinguri =

     

    binary scan [mcget {session.server.landinguri}] H* tmp;
    return "/fingerprint_accept?redirect=$tmp"

    This solution will allow to bypass OTP only if the fingerprint is the same with same username and within 24 hours time range.