Forum Discussion

Posterus_85681's avatar
Posterus_85681
Icon for Nimbostratus rankNimbostratus
Sep 29, 2015

clientless-mode, session-cookie and policy re-evaluation

Hi Everyone,

 

I am trying to use the inbuilt OTP functions within APM, so that they can be consumed by other systems that want to use OTP.

 

I have managed to use clientless-mode and have a system connect and execute the policy branch based on a specific URI and also pass header variables to choose if to generate or verify OTP. The session also return the MRHSession cookie so that this can be used to connect back to the same session, to do OTP verification.

 

The issue i am having is that when I connect back to the APm using an existing session (using the MRHsession cookie) i get a 504 received failure. I assume this is because when you connect back using a cookie the APM policy is not run again.

 

How can i get the policy to run again so that i can perform an OTP verification, based on a known SessionID?

 

7 Replies

  • Hi,

     

    clientless mode is a dedicated mode to authenticate user in one request.

     

    the session status must be Allow or deny at the end of the session.

     

    OTP password must be entered within the session.

     

    I'm not sure you can use OTP with clientless mode. you can try SWG-explicit profile type instead of clientless mode (SWG-explicit profile enter in a kind of clientless mode, but supporting ip source based session)

     

  • Hi Stan,

    This is what i have done to get around the issues you mentioned above. It works, but i don't know if its the most efficient way to do it or if it can be improved. I can come back into the same access session by presenting a cookie (this is how i execute the OTP verification)

    when HTTP_REQUEST { HTTP::header insert "clientless-mode" 1

    set otp_generated [ACCESS::session data get "session.otp.assigned.val"]
    set otp_to_verify [HTTP::header otp]
    set otp_status "failed"
    
    if { ($otp_to_verify) equals ($otp_generated) }
       { set otp_status "success" }
    
    if { ([HTTP::header otpmode] equals "generate") }{}
    
    if { ([HTTP::header otpmode] equals "verify") }
       { HTTP::respond 200 otp_status $otp_status Connection Close }
    

    }

    when ACCESS_SESSION_STARTED { ACCESS::session data set "session.custom.otpmode" [string trim [HTTP::header otpmode]] }

    when ACCESS_POLICY_COMPLETED { ACCESS::respond 200 OTP [ACCESS::session data get "session.otp.assigned.val"] SID [ACCESS::session data get "session.user.sessionid"] Connection Close } }

  • Hi,

    when ACCESS_POLICY_COMPLETED is raised, you cannot reevaluate the policy.

    if you want to execute a irule in the policy evaluation, you can raise ACCESS_POLICY_AGENT_EVENT event:

    when ACCESS_POLICY_AGENT_EVENT {
     if {[ACCESS::policy agent_id] == "otp"} {
     ACCESS::respond 200 OTP [ACCESS::session data get "session.otp.assigned.val"] SID [ACCESS::session data get "session.user.sessionid"] Connection Close } 
    }
    

    In ACCESS_POLICY_COMPLETED event, filter answer with Access policy result:

    when ACCESS_POLICY_COMPLETED {
         Authentication request for non bowser user-agent session denied
        if { ([ACCESS::policy result] equals "deny") } {
            ...
        }
    }
    
  • Hi Everyone,

     

    I think this needs a bit of clarification. I have managed to make the F5 APM work like a web services API, so that other external systems can utilise the built in OTP generation/verficiation. I will show the code and how it works below. I would like some feedback as to how i could improve it (if it can be improved).

     

    HOW IT WORKS

     

    GENERATE OTP CODE

     

    External System --> (calls) F5 APM (using a HTTPS POST) and passing a header variable "otpmode", that is used to select if the ext system wants to generate or verify the otp code.

     

    POST https://fqdn.com/otp HTTP/1.1
    User-Agent: Fiddler
    Host: fqdn.com
    Content-Length: 0
    otpmode: generate

    A response is then received as follows, with a header variable "otp" which is the OTP code generated in the F5 APM and also gets returned the cookie for the APM session. This OTP code can then be used by the external system (send via email or SMS for user/other to use)

     

    HTTP/1.0 200 OK
    OTP: 623177
    SID: xxxxx
    Server: BigIP
    Connection: Close
    Set-Cookie: LastMRH_Session=xxxxx;path=/;secure
    Set-Cookie: MRHSession=xxxxx;path=/;secure
    Content-Length: 0

    VERIFY OTP CODE

     

    External System --> (calls) F5 APM (using a HTTPS POST) and passing a header variable "otpmode", that is used to select if the ext system wants to generate or verify the otp code (in this case verify) and the OTP code that needs to be verified. It also passes the cookie so the system rejoins to the APM session it created in the generation activity.

     

    POST https://fqdn.com/otp HTTP/1.1
    User-Agent: Fiddler
    Host: fqdn.com
    Content-Length: 0
    otpmode: verify
    otp: 536484
    Cookie: MRHSession=xxxxx;path=/;secure

    A response is then received telling the ext system if the code sent for verification is correct.

     

    HTTP/1.0 200 OK
    OTP_status: success
    Server: BigIP
    Connection: Close
    Set-Cookie: LastMRH_Session=xxxxx;path=/;secure
    Set-Cookie: MRHSession=xxxxx;path=/;secure
    Content-Length: 0

    CODE TO MAKE THIS WORK

     

    iRULE

     

    when HTTP_REQUEST {
        HTTP::header insert "clientless-mode" 1
        set otp_generated [ACCESS::session data get "session.otp.assigned.val"]
        set otp_to_verify [HTTP::header otp]
        set otp_status "failed"
    
        if { ($otp_to_verify) equals ($otp_generated) }
           { set otp_status "success" }
    
        if { ([HTTP::header otpmode] equals "generate") }{}
    
        if { ([HTTP::header otpmode] equals "verify") }
           { HTTP::respond 200 otp_status $otp_status Connection Close }}
    
    when ACCESS_SESSION_STARTED {
        ACCESS::session data set "session.custom.otpmode" [string trim [HTTP::header otpmode]]
      }
    
    when ACCESS_POLICY_COMPLETED {
        ACCESS::respond 200 OTP [ACCESS::session data get "session.otp.assigned.val"] SID [ACCESS::session data get "session.user.sessionid"] Connection Close
         }
         }
    }

    APM POLICY

     

    The APM policy is basically as follows:

     

    -> Blank Box, which looks at "optmode" and selects branch as either "generate" or "verify"
    -> "Generate" branch then goes to "OTP Generate" -> faallback -> Allow
    -> "Verify" branch then goes to "OTP verify" -> Success or Fallback -> Allow
  • So, does it work???

    APM session cannot be re-evaluated... if you want to store OTP password, you can create a table value in the generate branch and read it in the verify branch:

    when ACCESS_POLICY_AGENT_EVENT {
        switch -glob [string tolower [HTTP::header "User-Agent"]] {
        "otpgenerate" { table add -subtable "OTP" [ACCESS::session data get "session.logon.last.username"] [ACCESS::session data get "session.otp.assigned.val"] indef 60 }
        "otpverify" { ACCESS::session data set "session.otp.assigned.val" [table lookup -subtable "OTP" [ACCESS::session data get "session.logon.last.username"]] }
        }
    }
    

    you must add irule event boxes in the VPE to raise this irule with IDs otpgenerate or otpverify.

  • It does work. Because the APM policy can not be re-evaluated thats why we connect back with MRH cookie and then compare the OTP code to verify from the ext system via header variable and compare this to the session.otp.assigned.val value that was generated (this is done in the http request section)

     

    • Stanislas_Piro2's avatar
      Stanislas_Piro2
      Icon for Cumulonimbus rankCumulonimbus
      When I look in your configuration, everything is allowed... there is no reject if the OTP code is wrong or the client does not provide a OTP code. If the first request contains generate, the APM allow the connection... if in the following requests, there is no generate or verify, the irule allow connection. the decision to allow or not the connection is not made by APM but by the client which receive the OTP status.